Jackson serialization duplicate field with @JsonAnyGetter

Viewed 424

I have my DTO class with predefined fields and map for non-mapped. When otherFields map contains field with same name (field1 key) jackson serialize both of them and I have non-valid json like

{
"field1": "value",
"field1": "otherValue"
}
public class DTO implements Serializable {

    private String field1;

    @JsonIgnore
    @JsonAnySetter
    private final Map<String, Object> otherFields = new LinkedHashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getOtherFields() {
        return otherFields;
    }

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }
}

Is there a way in this case pick one only value? For my case one from map should have priority.

1 Answers

The simplest solution I would propose is to ignore property and in getter marked by JsonAnyGetter annotation add extra logic which would check this condition:

class DTO {

    @JsonIgnore
    private String field1;

    private final Map<String, Object> otherFields = new LinkedHashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getOtherFields() {
        otherFields.putIfAbsent("field1", field1);

        return otherFields;
    }

    @JsonAnySetter
    public void setOtherFields(String key, Object value) {
        otherFields.put(key, value);
    }

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }
}

It is simple, but breaks getter by modifying otherFields Map. We can improve it by adding one classical getter and one for a Jackson:

class DTO {

    private String field1;
    private final Map<String, Object> otherFields = new LinkedHashMap<>();

    @JsonIgnore
    public Map<String, Object> getOtherFields() {
        return otherFields;
    }

    @JsonAnyGetter
    private Map<String, Object> internalJacksonGetOtherFields() {
        otherFields.putIfAbsent("field1", field1);

        return otherFields;
    }

    @JsonAnySetter
    public void setOtherFields(String key, Object value) {
        otherFields.put(key, value);
    }

    @JsonIgnore
    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }
}
Related