@JsonTypeInfo with EXTERNAL_PROPERTY doesn't handle arrays of polymorphic types
See original GitHub issueWhile the JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY works fine normally, there is an issue when using it along with @JsonTypeInfo and its JsonTypeInfo.As.EXTERNAL_PROPERTY feature (regular PROPERTY works fine). Below is an example test case to illustrate the issue:
public static class Foo {
public String msg;
}
public static class FooA extends Foo {
public String hey;
}
public static class FooB extends Foo {
public String whoa;
}
public static class Holder {
public String footype;
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
property = "footype")
@JsonSubTypes({@JsonSubTypes.Type(value=FooA.class, name="a"),
@JsonSubTypes.Type(value=FooB.class, name="b") })
@JsonFormat(with=JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public List<Foo> foo;
public Foo other;
}
@Test
public void testSVA() throws Exception
{
final InputStream stream = TestSingleValueArray.class.getResourceAsStream("footest.json");
Scanner s = new Scanner(stream);
final String json = s.useDelimiter("\\Z").next();
s.close();
final ObjectMapper mapper = new ObjectMapper();
final Holder holder = mapper.readValue(json, Holder.class);
}
I expected the above test to combine the external property and array features, but it instead throws the following error:
com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class TestSingleValueArray$Foo
at [Source: {
"footype": "a",
"foo": {
"msg": "Hello World",
"hey": "there"
},
"other": {
"msg": "Goodbye"
}
}; line: 3, column: 12] (through reference chain: Holder["foo"]->java.lang.Object[0])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:216)
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:962)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:127)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:93)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromObject(AsArrayTypeDeserializer.java:58)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1017)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.handleNonArray(CollectionDeserializer.java:341)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:259)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:249)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:490)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:260)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3788)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2779)
at TestSingleValueArray.testSVA(TestSingleValueArray.java:63)
Here is the input used to produce the above error:
{
"footype": "a",
"foo": {
"msg": "Hello World",
"hey": "there"
},
"other": {
"msg": "Goodbye"
}
}
Moving the footype field into Foo and switching from EXTERNAL_PROPERTY to a plain PROPERTY fixes the error, but of course is not quite the same.
Thanks in advance for your help!
Issue Analytics
- State:
- Created 8 years ago
- Comments:7 (2 by maintainers)
Top Results From Across the Web
Why does Jackson polymorphic serialization not work in lists?
I'm doing polymorphic serialization and it works perfectly when an object is on its own. But if you put the same object into...
Read more >Using @JsonTypeInfo annotation to handle polymorphic types
When used on properties (fields, methods), this annotation applies to values. That means when used on collection types (Collection, Map, arrays) ...
Read more >JsonTypeInfo (Jackson-annotations 2.14.0 API) - FasterXML
When used for properties (fields, methods), this annotation applies to values: so when applied to structure types (like Collection , Map , arrays),...
Read more >Polymorphic resolution without annotations, looking for ...
I am currently trying to handle polymorphic resolution without using the ... No, kind of type identifier to use is specified by @JsonTypeInfo...
Read more >Jackson-js: Powerful JavaScript decorators to ... - ITNEXT
jackson-js is heavily inspired by the famous Java FasterXML/jackson library. ... polymorphic type handling decorators: @JsonTypeInfo , @JsonSubTypes , and ...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@msmerc Unfortunately I don’t think I will have time to dig into this issue, although ideally would of course love to help.
The big problem, I think, is that
EXTERNAL_PROPERTY
basically CANNOT work for “real” arrays (that is,Collections
and arrays serialized as JSON Arrays) because there is no place in JSON Array to add properties. It could, in theory, work for the special case of “unwrapped” single-element array, but that seems fragile as it would only work for that one special case.I think that one good improvement would be for Jackson to detect this usage attempt at fail immediately with proper exception message (cannot use this combination of features), to at least let user know what is the issue.
So it seems the first problem is that collection / list properties annotated this way aren’t picked up and included in the
_externalTypeHnadler
because they don’t have avalueTypeDeserialiser
. See https://github.com/FasterXML/jackson-databind/blob/92f809dd161a80d0d5c519f78ea18443715970ad/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializerBase.java#L592Though I’m guessing this is just the tip of the iceberg and there would be more work after this.
@cowtowncoder Might it be possible to get some love for this issue? I’m guessing it’s unlikely!