解决JSON序列化继承Map的自定义对象时拿不到field属性值
2018年06月21日

如题,该问题在国外论坛上已有人提出来:https://stackoverflow.com/search?q=jackson+extends+map

但是并没有满意答案,都说要使用jackson的@JsonAnySetter注解:https://stackoverflow.com/questions/31320983/jackson-serialise-map-with-extra-fields,但是这样一来就和Jackson绑定死了,换成Gson或者FastJSON就不灵了。


现在,我把问题,清楚的描述一遍,直接上代码:

class Foo<T> extends HashMap<Object, Object> {
    private T data;
    public Foo() {}
    public Foo(T data) {
        this.data = data;
        put("AAAA", data);
    }
    public T getData() {
        return data;
    }
    public void setData(T data) {
        this.data = data;
    }
}

Foo类继承了HashMap,而且有一个私有的属性 data,经过json序列化后,data属性丢失,被放到了map中,

当反序列化时,data属性就为null了。测试代码如下:

Foo foo = new Foo("XXXXXXXXXXXXX");
String json = Json.toJSONString(foo);//UT.Json.
System.out.println(json);
//json = "{\"data\": \"xxxxxxxxx\", \"AAAA\":\"XXXXXXXXXXXXX\"}";
foo = Json.parseObject(json, Foo.class);
System.out.println(foo);
System.out.println(foo.getData()); // 为null

Jackson和Fastjson都是如此,究其原因,是因为序列化和反序列化时,Foo类被当做Map处理了。


前面说了,国外论坛上那些解决方案都不好,我想到了一个简单有效的方案,就是修改get方法:

class Foo<T> extends HashMap<Object, Object> {
    private T data;
    public Foo() {}
    public Foo(T data) {
        this.data = data;
        put("AAAA", data);
    }
    public T getData() {
        if(data!=null) {
          return data;
        }
        return super.get("data");
    }
    public void setData(T data) {
        this.data = data;
    }
}

就是 get的时候,如果拿不到,就调用map.get(key)方法获取数据。

这样完美解决问题,不需要对JSON配置进行任何修改。