Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed object with anchor throws Already had POJO for id #231

Closed
almson opened this issue Nov 10, 2020 · 6 comments
Closed

Typed object with anchor throws Already had POJO for id #231

almson opened this issue Nov 10, 2020 · 6 comments
Labels
yaml Issue related to YAML format backend
Milestone

Comments

@almson
Copy link

almson commented Nov 10, 2020

Tested with jackson-dataformat-yaml 2.11.3

package foo

import com.fasterxml.jackson.annotation.JsonIdentityInfo;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonSubTypes.Type;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import java.util.List;
import org.junit.Test;

public class JacksonYamlTest {
    
    static class Container {
        @JsonProperty
        List<Base> list;
    }
    
    @JsonTypeInfo(use = Id.NAME)
    @JsonSubTypes({@Type(name="Derived", value=Derived.class)})
    @JsonIdentityInfo(generator = ObjectIdGenerators.StringIdGenerator.class)
    static class Base {
        
    }
    
    static class Derived extends Base {
        @JsonProperty
        String a;
    }
    
    @Test
    public void typedObjectIdTest() throws Exception {
        
        String yaml = "list:\n" +
                      "    - !Derived &id1\n" +
                      "        a: foo";
        
        ObjectMapper mapper = new ObjectMapper (new YAMLFactory());
        Container container = mapper.readValue (yaml, Container.class);
        
        System.out.println (((Derived)container.list.get(0)).a);
    }
}

throws

com.fasterxml.jackson.databind.JsonMappingException: Already had POJO for id (java.lang.String) [[ObjectId: key=id1, type=com.fasterxml.jackson.annotation.ObjectIdGenerators$StringIdGenerator, scope=NONE]] (through reference chain: JacksonYamlTest$Container["list"]->java.util.ArrayList[0])
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:397)
	at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:368)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeWithObjectId(CollectionDeserializer.java:406)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:277)
	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.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3468)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3436)
	at JacksonYamlTest.typedObjectIdTest(JacksonYamlTest.java:41)

the problem is that SimpleObjectIdResolver.bindItem is called twice. Possibly, BeanDeserializerBase:1188 is not necessary at all.

@almson
Copy link
Author

almson commented Nov 10, 2020

Btw, leaving out the anchor also causes parsing to fail with a different exception:

Missing type id when trying to resolve subtype of [simple type, class JacksonYamlTest$Base]: missing type id property '@type' (for POJO property 'list')
 at [Source: (StringReader); line: 3, column: 15] (through reference chain: JacksonYamlTest$Container["list"]->java.util.ArrayList[0])
	at com.fasterxml.jackson.databind.exc.InvalidTypeIdException.from(InvalidTypeIdException.java:43)
	at com.fasterxml.jackson.databind.DeserializationContext.missingTypeIdException(DeserializationContext.java:1794)
	at com.fasterxml.jackson.databind.DeserializationContext.handleMissingTypeId(DeserializationContext.java:1323)
	at com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase._handleMissingTypeId(TypeDeserializerBase.java:303)
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedUsingDefaultImpl(AsPropertyTypeDeserializer.java:166)
	at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:107)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeWithType(BeanDeserializerBase.java:1209)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeWithObjectId(CollectionDeserializer.java:395)
	at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:277)
	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.impl.FieldProperty.deserializeAndSet(FieldProperty.java:138)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:293)
	at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:156)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3468)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3436)
	at JacksonYamlTest.typedTest(JacksonYamlTest.java:54)

for input

list:
    - !Derived
        a: foo

Removing @JsonIdentityInfo solves the problem.

@cowtowncoder
Copy link
Member

Looking into this: for some reason, OBject Id registration done twice. Not yet sure if it is due to buffering needed (due to type info), or differing Object Id handling wrt YAML (since it has native construct, unlike json and most other formats).

@cowtowncoder
Copy link
Member

Or, possibly this is actually due to messy translocation of Object Id (YAML anchor) during YAMLParser handling, and nothing to do with databinding. Gnarly.

@cowtowncoder
Copy link
Member

Ended up adding work-around (see FasterXML/jackson-annotations#180) that will avoid the issue, pass the test.

@cowtowncoder cowtowncoder modified the milestones: 2.12.0, 2.12.0-rc2 Nov 12, 2020
cowtowncoder added a commit that referenced this issue Nov 12, 2020
@almson
Copy link
Author

almson commented Nov 12, 2020

What about the second problem? Should I open a separate issue? Reproducing it is to just leave out the anchor in the yaml.

@cowtowncoder
Copy link
Member

@almson Yes, please open separate issue with changed reproduction, refer this issue as background.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
yaml Issue related to YAML format backend
Projects
None yet
Development

No branches or pull requests

2 participants