Skip to content

@JsonTypeInfo with As.EXTERNAL_PROPERTY doesn't work if external type property is referenced more than once #291

@Starkom

Description

@Starkom

Test model:

    public static interface F1 {}

    public static class A implements F1 {
        public String a;
    }

    public static class B implements F1 {
        public String b;
    }

    public static interface F2 {}

    public static class C implements F2 {
        public String c;
    }

    public static class D implements F2{
        public String d;
    }

    public static class Container {
        public String type;

        @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
        @JsonSubTypes({
                @JsonSubTypes.Type(value = A.class, name = "1"),
                @JsonSubTypes.Type(value = B.class, name = "2")})
        public F1 field1;

        @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
        @JsonSubTypes({
                @JsonSubTypes.Type(value = C.class, name = "1"),
                @JsonSubTypes.Type(value = D.class, name = "2")})
        public F2 field2;
    }

Test JSON:

{
 "type" : "1",
 "field1" : {
   "a" : "AAA"
 },
 "field2" : {
   "c" : "CCC"
 }
}

Stacktrace:

com.fasterxml.jackson.databind.JsonMappingException: Unexpected token (VALUE_NULL), expected VALUE_STRING: need JSON String that contains type id (for subtype of F2)
at [Source: java.io.StringReader@b2fe7658; line: 9, column: 1]
at com.fasterxml.jackson.databind.DeserializationContext.wrongTokenException(DeserializationContext.java:668)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._locateTypeId(AsArrayTypeDeserializer.java:144)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:101)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromObject(AsArrayTypeDeserializer.java:69)
at com.fasterxml.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:106)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:462)
at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:107)
at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler._deserializeAndSet(ExternalTypeHandler.java:253)
at com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler.complete(ExternalTypeHandler.java:162)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:715)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithExternalTypeId(BeanDeserializer.java:664)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:274)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2034)

The reason:

com.fasterxml.jackson.databind.deser.impl.ExternalTypeHandler:262

    public static class Builder
    {
        private final ArrayList<ExtTypedProperty> _properties = new ArrayList<ExtTypedProperty>();
        private final HashMap<String, Integer> _nameToPropertyIndex = new HashMap<String, Integer>();

        // note: signature changed between 2.1.0 and 2.1.1 (alas!)
        public void addExternal(SettableBeanProperty property, TypeDeserializer typeDeser)
        {
            Integer index = _properties.size();
            _properties.add(new ExtTypedProperty(property, typeDeser));
            _nameToPropertyIndex.put(property.getName(), index);
            _nameToPropertyIndex.put(typeDeser.getPropertyName(), index);
        }

addExternal() method is called in property loop, but _nameToPropertyIndex is Map, so addExternal() can't be called twice correctly for property "type".

So _nameToPropertyIndex doesn't contain type=0: {field1=1, type=1, field2=0}

I think type of _nameToPropertyIndex should be changed from HashMap[String, Integer] to HashMap[String, Set[Integer]]. It occurs several changes in ExternalTypeHandler. I've patched jar locally and it solved my problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions