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

@JsonAnySetter with @JsonUnwrapped: deserialization fails with arrays #349

Closed
hdave opened this issue Nov 19, 2013 · 10 comments
Closed

@JsonAnySetter with @JsonUnwrapped: deserialization fails with arrays #349

hdave opened this issue Nov 19, 2013 · 10 comments
Milestone

Comments

@hdave
Copy link

hdave commented Nov 19, 2013

My application makes heavy use of the @JsonAnySetter/Getter annotations which is currently throwing an exception when deserializing an JSON array of strings as a property value:

Can not deserialize instance of java.lang.Object out of END_ARRAY token at [Source: org.apache.cxf.transport.http.AbstractHTTPDestination$1@7a5d231e; line: 22, column: 5] (through reference chain: com.mycorp.core.web.rest.dto.ItemDTO["ZoomLinks"])
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:575)
at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:569)
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer.deserialize(UntypedObjectDeserializer.java:90)
at com.fasterxml.jackson.databind.deser.SettableAnyProperty.deserialize(SettableAnyProperty.java:98)
at com.fasterxml.jackson.databind.deser.SettableAnyProperty.deserializeAndSet(SettableAnyProperty.java:88)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeWithUnwrapped(BeanDeserializer.java:515)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:271)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
at com.fasterxml.jackson.databind.ObjectReader._bind(ObjectReader.java:1179)
at com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:635)

Here is the Java code:

public void addProperty(String key, Object value) {
if (props == null)
{ props = new HashMap<String, Object>(); }
props.put(key, value);
}
@JsonAnyGetter
public Map<String, Object> getProperties()
{ return props; }

and here is some sample JSON that will fail:

{ "_type" : "IST",
 "_spacename" : "Foo Models",
 "_name" : "BLAH-New",
 "_description" : "namespace.name: X THIN FIR.DR-WD12-New",
 "ZoomLinks": [ "foofoofoofoo", "barbarbarbar" ] }
@cowtowncoder
Copy link
Member

Hmmh. I can not reproduce this with simple tests for UntypedObjectDeserializer or any setter handling, so I am guessing this might be related to some other aspects, such as enabling of "default typing" or something? How does ItemDTO look like?

@hdave
Copy link
Author

hdave commented Nov 19, 2013

Here's the code for ItemDTO -- the other child objects are again, simple value objects.

I probably should have mentioned that I use a paired combination of Jackson and Jax-B annotations (in that order).

@XmlAccessorType(XmlAccessType.PROPERTY)
@XmlType(name = "item", propOrder = { "_status", "_links", "_embedded", "_identity" })
public class ItemDTO
        implements VisitableDto {

    @XmlElement(name = "_status")
    public StatusDTO status = null;

    private Map<String, Object> props = null;

    @JsonAnySetter
    public void addProperty(String key, Object value) {
        if (props == null) {
            props = new HashMap<String, Object>();
        }
        props.put(key, value);
    }

    @JsonAnyGetter
    public Map<String, Object> getProperties() {
        return props;
    }

    @JsonUnwrapped
    @XmlElement(name = "_identity")
    public IdentityDTO identity = null;

    @XmlElement(name = "_links")
    public LinksDTO hlinks = null;

    @XmlElement(name = "_embedded")
    public EmbeddedDTO embedded = null;

    @XmlElement(name = "_metadata")
    public MetadataDTO metadata = null;

    public ItemDTO() {
        super();
    }

}

@hdave
Copy link
Author

hdave commented Nov 19, 2013

Upon trying my own tests by hand, I think the problem is that ItemDTO also has @JsonUnwrapped. When I take that out, I seem to get past this problem.

@cowtowncoder
Copy link
Member

Ah. That sounds plausible... combination of the two could be somewhat tricky. I can try to write a unit test; ideally that would be supported. But implementation of @JsonUnwrapped is seriously fragile and ugly, FWIW.

@hdave
Copy link
Author

hdave commented Nov 21, 2013

Right. I kind of agree that having them both is kind of asking for trouble. Is it possible to have two or more @JsonUnwrapped in the same class? If yes, then this could/should be supported. If not, then this should probably not be allowed either. In the end, having multiple unwrapped property collections supported would be cool, but its asking for collisions eventually. Up to you...

@cowtowncoder
Copy link
Member

Yes, two isntances of @JsonUnwrapped are allowed. I am not saying that use of unwrapped & any-getters/setters could not work, conceptually (any-getter/setter is a fallback, and should have lower precedence).
But it may be difficult to make that work, so on short term you probably want to look for alternative setups. Even if we eventually make combination work.

@hdave
Copy link
Author

hdave commented Nov 21, 2013

ok will do, thanks.

@borball
Copy link

borball commented Jan 14, 2017

@cowtowncoder It seems JsonAnySetter and JsonUnwrapped can work together in 2.9.0-SNAPSHOT but not in 2.8.6. I have added one test case here:
https://github.com/borball/jackson-test/blob/master/src/test/java/com/fasterxml/jackson/test/JacksonTest.java#L15-L19
With 2.9.0-SNAPSHOT I can successfully get bean object refundQuery but with 2.8.6, it is null.

@refacktor
Copy link

This seems broken in 2.9.9, but in a different way... the @JsonUnwrapped fields are duplicated in the @JsonAnySetter. Is this a regression or always been this way?

@cowtowncoder
Copy link
Member

I think that the way things are implemented duplicates would always have occurred.

Later issue #1811 cover the problem: I hope this can be resolved in 3.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants