Vladimir B.
Vladimir B.

Reputation: 41

Jackson custom serializer serialize field twice if property name not equal field name

If you use custom serialization, you can get an unexpected effect if property name not equal to field name. Why the field is serialized twice?

My code sample:

class Mode {
    @JsonProperty("mode")
    @JsonSerialize(using = ModeSerializer.class)
    private boolean isPublic;

    public Mode(boolean isPublic) {
        this.isPublic = isPublic;
    }

    public boolean isPublic() {
        return isPublic;
    }
}

Here my custom field serializer:

class ModeSerializer extends JsonSerializer<Boolean> {

        @Override
        public void serialize(Boolean value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
            String out = "private";
            if (value) {
                out = "public";
            }
            gen.writeString(out);
        }
    }

And here the test:

public class Test {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        Mode mode = new Mode(true);
        String toJson = mapper.writeValueAsString(mode);
        System.out.println(toJson);
    }
}

And as a result I receive:

{"public":true,"mode":"public"}

What am I doing wrong?

Upvotes: 3

Views: 2188

Answers (2)

Vladimir B.
Vladimir B.

Reputation: 41

Thanks for the detailed answer.
You are absolutely right I need to isolate getter Public, and this can do not only with renaming this method, but also using the annotation @JsonIgnore to the method. Like this:

class Mode {
    @JsonProperty("mode")
    @JsonSerialize(using = ModeSerializer.class)
    private boolean isPublic;

    public Mode(boolean isPublic) {
        this.isPublic = isPublic;
    }

    @JsonIgnore
    public boolean isPublic() {
        return isPublic;
    }
}

This works for me.

Upvotes: 1

Manos Nikolaidis
Manos Nikolaidis

Reputation: 22244

Jackson follows java beans conventions for getter methods.

According to these isPublic is a getter for a boolean property named public, different than the isPublic field in Mode. Jackson will serialize that as "public":true.

In addition to that, you specify a @JsonProperty that Jackson will serialize in a field with the provided name mode.

@JsonDeserialize annotation on the field would have caused Jackson to ignore the getter if the name of the field matched the one implied by the getter method. The corresponding getter method for a boolean field named isPublic would be isIsPublic()

The fact that you specify a Json field name of mode doesn't affect the above.

Upvotes: 1

Related Questions