我试图使用@JsonItentityInfo序列化关系以避免循环引用。我创建了一个测试来测试序列化的结果,我发现jackson的行为不像我预期的那样。序列化并不是我想象的那样,事实上,当我试图对序列化的对象进行反序列化时,会抛出异常。我使用的代码是:
public class Test {
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public static class A {
private final String id;
private final String name;
private final B b;
public A(final String id, final String name, final B b) {
this.id = id;
this.name = name;
this.b = b;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public B getB() {
return this.b;
}
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public static class B {
private final String id;
private final String name;
public B(final String id, final String name) {
this.id = id;
this.name = name;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
public static void main(final String[] args) {
try {
System.out.println(
new ObjectMapper().writeValueAsString(new A("1", "a", new B("2", "b"))));
} catch (final JsonProcessingException e) {
e.printStackTrace();
}
}
}
根据我的理解,输出应该是
{"id":"1","name":"a","b":"2"}
但是测试返回
{"id":"1","name":"a","b":{"id":"2","name":"b"}}
实际上,当尝试读取序列化字符串时,jackson会抛出异常。我做错了什么?
谢谢大家的帮助
编辑这个例子不完整。对象应该被包裹在另一个对象中,因此它们两个是序列化的。
package lvillap.deliverytoolsserver.domain;
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonIdentityReference;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Test {
private final A a;
private final B b;
public Test(final A a, final B b) {
this.a = a;
this.b = b;
}
public A getA() {
return this.a;
}
public B getB() {
return this.b;
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public static class A {
private final String id;
private final String name;
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = true)
private final B b;
public A(final String id, final String name, final B b) {
this.id = id;
this.name = name;
this.b = b;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public B getB() {
return this.b;
}
}
public static class B {
private final String id;
private final String name;
public B(final String id, final String name) {
this.id = id;
this.name = name;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
}
public static void main(final String[] args) {
try {
final B b = new B("2", "b");
final A a = new A("1", "a", b);
System.out.println(new ObjectMapper().writeValueAsString(new Test(a, b)));
} catch (final JsonProcessingException e) {
e.printStackTrace();
}
}
}
以这种方式实现时,结果是预期的:{"a"{"id"1","name":"a","b":"2";},"b":{"id"2","name":"b"}}
谢谢大家的帮助!
在默认情况下,你会得到你应该得到的。
你能做的就是像下面这样改变你的class A
。
注意,我已经改变了getB()
方法。它不再返回class B
的实例。它返回class B
实例的id
属性。
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public static class A {
private final String id;
private final String name;
private final B b;
public A(final String id, final String name, final B b) {
this.id = id;
this.name = name;
this.b = b;
}
public String getId() {
return this.id;
}
public String getName() {
return this.name;
}
public String getB() {
return this.b.id;
}
}
您也可以为class B
创建自定义序列化器。
如果你想
{"id":"1","name":"a","b":"2"}
然后将private final B b;
更改为private final String b;
,删除B类并更改代码
new ObjectMapper().writeValueAsString(new A("1", "a", "2"));
也可以删除@JsonIdentityInfo
我认为一切都是直截了当的,对象Java将被转换为对象json,所以当你在class A
中包含class B
作为一个字段时,你有嵌套的json对象。