gdogaru
gdogaru

Reputation: 521

Jackson serializer produces invalid Json for subclass of Map

I have this piece of code, that serialises a subclass of Map using Jackson. Without the serializer registered I get a valid json, I use the serializer to get the name to lower case. However, the produced json looks like:

{:"two":"aaa":"one":"aaa"}

Any idea why? How to fix?

@Test
public void test_serialization() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();
    SimpleModule module = new SimpleModule("JSONModule", new Version(1, 0, 0, null, null, null));
    module.addSerializer(Circle.class, new CircleSerializer());
    module.addKeySerializer(Circle.class, new CircleSerializer());
    mapper.registerModule(module);

    CircleMap statistics = new CircleMap();
    statistics.put(Circle.ONE, "aaa");
    statistics.put(Circle.TWO, "aaa");

    System.out.println(mapper.writeValueAsString(statistics));
}

enum Circle {
    ONE, TWO
}

static class CircleMap extends HashMap<Circle, String> {
}

static class CircleSerializer extends JsonSerializer<Circle> {
    @Override
    public void serialize(Circle value, JsonGenerator gen, SerializerProvider provider) throws IOException, JsonProcessingException {
        gen.writeString(value.name().toLowerCase());
    }
}

Upvotes: 1

Views: 895

Answers (1)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280030

Replace

gen.writeString(value.name().toLowerCase());

with

gen.writeFieldName(value.name().toLowerCase());

You're serializing a key. That's interpreted as a JSON field name so you have to use that method. writeString javadoc states

Method for outputting a String value. Depending on context this means either array element, (object) field value or a stand alone String;

You're straight up writing the string value. That's not what you want.

Note that you'll need a different serializer for keys and for normal values.

Upvotes: 2

Related Questions