我目前正在尝试序列化一个对象树,然后反序列化它,以便所有引用保持不变。问题是,保存这些引用的字段是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中完成的