Serialising generic value classes via Reference Types (like Optional) fails to include type information
See original GitHub issueAfter going through a couple issues, I came to understand that Jackson always uses declared type of value to figure out whether to include type information. This is done to ensure that type settings are identical between serialization and deserialization.
However isn’t that statement false for templated class?. This robustness would be better ensured if the type id settings would be bound to declared types for all untemplated classes but were bound to both declaration and component classes for templated classes. This would imply obtaining the type information at runtime, thus serialisation/deserialisation of templated classes would be a little bit less efficient but that drawback would be negligeable at least in my case.
This would allow for serialisation/deserialisation of Templated classes who’s component class are abstract ex. List<AbstractItem>
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(name = "ItemADto", value = ItemADto.class)
@JsonSubTypes.Type(name = "ItemBDto", value = ItemBDto.class)
})
public abstract class AbstractItemDto {...}
@JsonTypeName("ItemADto")
public class ItemADto {...}
@JsonTypeName("ItemBDto")
public class ItemBDto {...}
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:20 (11 by maintainers)
Top GitHub Comments
Given the example I have a list of item’s who’s classes are part of a polymorphic hierarchy
When I serialize this list,
then the type information concerning ItemADto and ItemBDto are not serialized and therefor lost.
Since AbstractItemDto specifies the usage of a “type” attribute for JsonTypeInfo
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
I would expect the serialized string to contain the “type” attribute necessary for the list’s deserialization
this would allow me to effectively deserialise itemsJson into a list containing one instance of ItemADto and one instance of ItemBDto
@pwhissell Ah. No, it’s not because this is not supported, but due to Java Type Erasure. This is a FAQ. (type erasure meaning that runtime type can not be detected as anything but
List<?>
)My main suggestion is really to avoid ever using generic types as root value (that is, value directly passed to ObjectMapper/ObjectWriter). They are fine everywhere else, when reached via property, since generic signature is actually retained in class definition, and thereby accessible.
Instead, either:
class MyList extends ArrayList<Pojo> { }
But if you really really want to use
List
s,Map
s or generic POJOs as root values, you need to pass type parameter to work around type erasure:As things are, there may be issues here too, unfortunately, as this forces type for serializer to use
AbstractDTO
, and not just as base type. This may or may be a problem, depending on exactly where properties for subtypes exist. There is a filed issue to allow specifying just the base type (distinct from full value types), but it has not been implemented.