jackson-databind icon indicating copy to clipboard operation
jackson-databind copied to clipboard

@JsonAnySetter and @JsonUnwrapped deserialize property twice

Open jearton opened this issue 8 years ago • 1 comments

I did such test.

First define a pojo:

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

@Data
public class ESModel {

    private Long id;

    @JsonUnwrapped
    private Result result;

    private Map<String, Object> extra = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getExtra() {
        return extra;
    }

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

    @Data
    public static class Result {
        private String name;
    }
}

Then test serialization:

    @Test
    public void test001() {
        ESModel esModel = new ESModel();
        ESModel.Result child = new ESModel.Result();
        child.setName("aaa");
        Map<String, Object> map = new HashMap<>();
        map.put("age", 12);

        esModel.setId(1L);
        esModel.setResult(child);
        esModel.setExtra(map);
        System.out.println(JSON.toJSONString(esModel));
    }

The output is following which I expected.

{"id":1,"name":"aaa","age":12}

And then test deserialization:

        String json = "{\"id\":1,\"name\":\"aaa\",\"age\":12}";
        ESModel model = JSON.parseObject(json, ESModel.class);
        System.out.println(model);

The output is following which out of my expectation. The property 'name' has been deserialized twice.

ESModel(id=1, result=ESModel.Result(name=aaa), extra={name=aaa, age=12})

PS:The JSON utitliy class is follow:

public abstract class JSON {

    private static ObjectMapper objectMapper;

    static {
        objectMapper = new ObjectMapper();
        objectMapper.setTimeZone(TimeZone.getDefault());
        objectMapper.setSerializationInclusion(NON_ABSENT);
        objectMapper.disable(FAIL_ON_UNKNOWN_PROPERTIES);
        objectMapper.disable(READ_DATE_TIMESTAMPS_AS_NANOSECONDS);
        objectMapper.disable(WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
        objectMapper.disable(DEFAULT_VIEW_INCLUSION);
        objectMapper.enable(ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER);
        objectMapper.enable(PROPAGATE_TRANSIENT_MARKER);
    }

    /*-----------------------deserialization-----------------------*/

    public static <T> T parseObject(String json, Class<T> clazz) {
        try {
            return objectMapper.readValue(json, clazz);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }

    /*-----------------------serialization-----------------------*/

    public static String toJSONString(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (IOException e) {
            throw new JSONException(e.getMessage(), e);
        }
    }
}

jearton avatar Nov 01 '17 02:11 jearton