I'm serializing and deserializing a list including two objects, with circular references there.
First I tried ObjectIdGenerators.StringIdGenerator
as the generator.
//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]
}
This is the json serialized by StringIdGenerator, which doesn't make sense for the second instance(no type info there,just a 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"
]
]
Then I tried 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'
}
This is the json serialized by JSOGGenerator, which does make sense.
[
"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"
}
]
]
However, I got an InvalidTypeIdException
while deserializing.
And I found the property "@id" is not handled correctly.
See ObjectIdValueProperty._valueDeserializer._baseType
, which type is JSOGRef
and it can not parse "1"(String) as object id value.
My questions
- What's the correct way to deal with this?
- Do we have some other generator to try?