我正在序列化和反序列化一个包含两个对象的列表,在那里有循环引用。
首先,我尝试ObjectIdGenerators.StringIdGenerator
作为生成器。
//Using latest version for the dependencies
//jackson.version = 2.13.1
//jackson-jsog = 1.1.2
@NoArgsConstructor
@JsonIdentityInfo(generator = ObjectIdGenerators.StringIdGenerator.class)
public static class Outer {
@Setter
@Getter
private Inner inner;
}
@NoArgsConstructor
@JsonIdentityInfo(generator = ObjectIdGenerators.StringIdGenerator.class)
public static class Inner {
@Getter
private Outer outer;
public Inner(Outer outer) {
this.outer = outer;
outer.setInner(this);
}
}
public static void main(String[] args) throws Exception {
// There are circular references between Outer and Inner
Outer outer = new Outer();
Inner inner = new Inner(outer);
// Turn on type info
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfSubType(Object.class).build();
ObjectMapper mapper = new ObjectMapper()
.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.EVERYTHING,
JsonTypeInfo.As.PROPERTY);
List<Object> source = Lists.newArrayList(outer, inner);
String json = mapper.writeValueAsString(source);
System.out.println(json);
//This is the json serialized by StringIdGenerator, which doesn't make sense for the second instance(no type info there,just a UUID)
//See below
List<Object> target = mapper.readerForListOf(Object.class).readValue(json);
System.out.println(target);
//So I finally got an Outer instance and a string in the target list, not equal to source list at all
//[com.foo.bar.SomeTest$Outer@4b29d1d2, acb5231d-13de-4e22-92c6-cb1ec0530de1]
}
这是由 StringIdGenerator 序列化的 json,对于第二个实例没有意义(那里没有类型信息,只有一个 UUID)
[
"java.util.ArrayList",
[
{
"@class": "com.foo.bar.SomeTest$Outer",
"@id": "df6ed346-6b27-4983-8dc2-5c07ddfa8f8f",
"inner":
{
"@class": "com.foo.bar.SomeTest$Inner",
"@id": "acb5231d-13de-4e22-92c6-cb1ec0530de1",
"outer": "df6ed346-6b27-4983-8dc2-5c07ddfa8f8f"
}
},
"acb5231d-13de-4e22-92c6-cb1ec0530de1"
]
]
然后我尝试了JSOGGenerator
@NoArgsConstructor
@JsonIdentityInfo(generator = JSOGGenerator.class)
public static class Outer {
@Setter
@Getter
private Inner inner;
}
@NoArgsConstructor
@JsonIdentityInfo(generator = JSOGGenerator.class)
public static class Inner {
@Getter
private Outer outer;
public Inner(Outer outer) {
this.outer = outer;
outer.setInner(this);
}
}
public static void main(String[] args) throws Exception {
// There are circular references between Outer and Inner
Outer outer = new Outer();
Inner inner = new Inner(outer);
// Turn on type info
PolymorphicTypeValidator ptv = BasicPolymorphicTypeValidator.builder().allowIfSubType(Object.class).build();
ObjectMapper mapper = new ObjectMapper()
.activateDefaultTyping(ptv, ObjectMapper.DefaultTyping.EVERYTHING,
JsonTypeInfo.As.PROPERTY);
List<Object> source = Lists.newArrayList(outer, inner);
String json = mapper.writeValueAsString(source);
System.out.println(json);
//This is the json serialized by JSOGGenerator, which does make sense
//See below
List<Object> target = mapper.readerForListOf(Object.class).readValue(json);
//However, I got an InvalidTypeIdException while deserializing
//Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.voodoodyne.jackson.jsog.JSOGRef]: missing type id property '@class'
}
这是JSOGGenerator序列化的json,确实有道理。
[
"java.util.ArrayList",
[
{
"@class": "com.foo.bar.SomeTest$Outer",
"@id": "1",
"inner":
{
"@class": "com.foo.bar.SomeTest$Inner",
"@id": "2",
"outer":
{
"@ref": "1"
}
}
},
{
"@ref": "2"
}
]
]
但是,我有一段InvalidTypeIdException
时间反序列化。而且我发现属性“@id”没有正确处理。
看ObjectIdValueProperty._valueDeserializer._baseType
,这是哪种类型JSOGRef
,它不能将“1”(字符串)解析为对象 id 值。
我的问题
- 处理这个问题的正确方法是什么?
- 我们有其他的发电机可以尝试吗?