使用Jackson JSON解析器序列化ID时缺少标识信息

时间:2014-08-04 10:51:12

标签: java json jackson

我目前正在尝试序列化对象树并在之后对其进行反序列化,以便所有引用保持不变。问题是,持有这些引用的字段是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

元素的第一次出现'正确反序列化,因为它附加了类型信息。然而,第二个不是,因为当仅序列化id时不添加类型信息。 id被反序列化为Integer,因为解析器不会将其识别为id,因为该字段的类型为' Object'。

所以问题是:有没有办法告诉杰克逊附加类型信息,即使只写了id,以便反序列化的元素'是一样的吗?

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

感谢您的时间。

1 个答案:

答案 0 :(得分:0)

好的,我想我已经弄明白了。

当使用@JsonTypeInfo时,杰克逊尝试在 SAME 对象作为已经序列化的对象时缩写对象。在这种情况下,它不包括数据,而是仅包括对先前序列化对象的引用。这是有道理的。

但出于某种原因,使用Object元素中的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来实现它,一切都会成功。

这是我最终的结果:

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进行了这项测试