在杰克逊中反序列化对象引用



我正在尝试使用ObjectMapper反序列化对象引用($ref)。

public class Foo {
@JsonProperty("bar")
private Bar bar;
@JsonProperty("bar")
public Bar getBar() {
return bar;
}
@JsonProperty("bar")
public void setBar(Bar bar) {
this.bar = bar;
}
}

test.json 这是我正在尝试反序列化的 json 文件。 这是引用对象/json引用的正确方法吗?

{  
"bar": {"$ref": "/bar.json"}
}

反序列化程序.java

ObjectMapper objectMapper = new ObjectMapper();
//load class
URL url = Deserializer.class.getClassLoader().getResource("test.json");
//deserialize 
objectMapper.readValue(url, Foo.class);

结果创建一个具有"bar"附加属性的Foo pojo:"$ref":"/bar.json",而不是反序列化它。是否需要实现反序列化接口并手动反序列化节点?

传统上,在Comp Sc.中,这个问题是使用所谓的"指针旋转"来解决的。

这意味着,如果你有一个对象 A,其中包含对 B 的引用,并且你想要序列化这个结构(然后反序列化它),你需要"取消"指向 B 的指针到一个"名称"(唯一标识实例 B 的标识符),将其写入磁盘。反序列化时,您将采用该名称,找到它指向 (B) 的实例,然后将名称"切换"回指向 B 的正确指针。

现在,在Java中,指针被称为引用,但它是一样的。

下面是一个示例来说明:

originalA = { "id":"id_a", "ref_to_b": originalB}
originalB = { "id":"id_b" }

应用取消排行:

readyForSerializationA = { "id":"id_a", "ref_to_b": "id_b"}
readyForSerializationB = { "id": "id_b" }

然后写入存储/从存储回读。

应用旋转:

deserializedB = { "id":"id_b" }
deserializedA = { "id": "id_a", "ref_to_b": deserializedB}

一种可能的方法是首先反序列化所有对象,将它们放入HashMap中,然后在第二次传递中,从JSON(旋转)中的各种ObjectID中查找ObjectReference。

进一步阅读:https://en.wikipedia.org/wiki/Pointer_swizzling

您需要将其存储{"$ref": "/bar.json"}为地图。这是最简单的存储方法。

例:

public class Foo {
@JsonProperty("bar")
private Map<String, Bar> bar;
@JsonProperty("bar")
public Map<String, Bar> getBar() {
return bar.get("$ref");
}
@JsonProperty("bar")
public void setBar(Map<String, Bar> bar) {
this.bar = bar;
}
}

只有这样,它才会在 Bar 对象中获取 $ref 的值。否则,数据将采用不正确的格式,Bar 对象会将整个柱线值纳入其中。

最新更新