使用Jackson JSON解析器序列化id时缺少身份信息



我目前正在尝试序列化一个对象树,然后反序列化它,以便所有引用保持不变。问题是,保存这些引用的字段是Object类型的。下面的代码片段

public class Main {
    public static void main(String[] args) throws IOException {
        Root r = new Root();
        Element e = new Element();
        e.s = "test";
        r.o1 = e;
        r.o2 = e;
        ObjectMapper ma = new ObjectMapper();
        ma.addMixInAnnotations(Object.class, Mixin.class);
        String json = ma.writeValueAsString(r);
        System.out.println(json);
        Root r2 = ma.readValue(json, Root.class);
        System.out.println(r2.o1.getClass());
        System.out.println(r2.o2.getClass());
        System.out.println(r2.o1 == r2.o2);
    }

    public static class Root {
        public Object o1;
        public Object o2;
    }
    public static class Element {
        public String s;
    }
    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
    @JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
    public static class Mixin {
    }
}

的结果如下:

{"@class":"Main$Root","@id":1,"o1":{"@class":"Main$Element","@id":2,"s":"test"},"o2":2}
Main$Element
java.lang.Integer
false

第一次出现的'Element'被正确反序列化,因为它附加了类型信息。但是第二个不是,因为只有id序列化时没有添加类型信息。该id被反序列化为一个Integer,因为解析器不能将其识别为id,因为该字段是'Object'类型。

所以问题是:是否有一种方法可以告诉Jackson即使只写id也要附加类型信息,这样反序列化的"元素"是相同的?

编辑:类型必须是Object,因为在我的用例中,内容实际上可以是任何东西,甚至是我无法控制的类。因此,主要问题是如何在引用本身中包含类型信息。

感谢您的宝贵时间。

好了,我想我明白了。

当使用@JsonTypeInfo时,Jackson会在相同的对象与已经序列化的对象相同时,尝试简化对象。在这种情况下,它不包括数据,而只包括对先前序列化对象的引用。这是有道理的。

然而,由于某种原因,在您的Root' object doesn't carry the identity and things break from there. If you create a dummy interface, use that as your base type, drop the MixIn on it and have元素中使用Object来实现它,这一切都行得通。

最后的结果是:

public static void main(String[] args) throws IOException {
    Root r = new Root();
    Element e = new Element();
    e.s = "test1";
    r.o1 = e;
    r.o2 = e;
    ObjectMapper ma = new ObjectMapper();
    ma.addMixInAnnotations(Root.class, Mixin.class);
    ma.addMixInAnnotations(Base.class, Mixin.class);
    String json = ma.writeValueAsString(r);
    System.out.println(json);
    Root r2 = ma.readValue(json, Root.class);
    System.out.println(r2.o1.getClass());
    System.out.println(r2.o2.getClass());
    System.out.println(r2.o1 == r2.o2);
}
public static class Root {
    public Base o1;
    public Base o2;
}
public interface Base {
}
public static class Element implements Base {
    public String s;
}
@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public static class Mixin {
}

得到以下输出:

{"@class":"Main$Root","@id":1,"o1":{"@class":"Main$Element","@id":2,"s":"test1"},"o2":2}
class Main$Element
class Main$Element
true

这个测试是在Jackson 2.3.3中完成的

最新更新