Skip to content

Polymorphic deserialization with EXTERNAL_PROPERTY fails if type property not marked as property #1527

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

Closed
prtmD opened this issue Feb 13, 2017 · 13 comments

Comments

@prtmD
Copy link

prtmD commented Feb 13, 2017

I have class as follows

class XYZ {
    private String type;

    private TypeSpecific typeSpecific;

    public TypeSpecific getTypeSpecific() {
        return typeSpecific;
    }

    @JsonTypeInfo(
		use = JsonTypeInfo.Id.NAME, 
		include = JsonTypeInfo.As.EXTERNAL_PROPERTY, 
		property = "type"			
		)
    @JsonSubTypes({		
		@JsonSubTypes.Type(value = ATypeSpecific.class, name = "a")
    })
    public void setTypeSpecific(TypeSpecific typeSpecific) {
        this.typeSpecific = typeSpecific;
    }
}

Class ATypeSpecific extends TypeSpecific.

I want to deserialize JSON
{"type":"b"}
where typeSpecific will be set as null in object. But I am getting following exception:

com.fasterxml.jackson.databind.JsonMappingException: Missing property 'typeSpecific' for external type id 'type'

How do I deserialize above mentioned JSON into the object? If @JsonTypeInfo requires 'typeSpecific' property during deserialization, then is there a way to add it into JSON before deserialization?

Dependency versions:
jackson-annotations: 2.7.0
jackson-core: 2.7.4
jackson-databind: 2.7.4

@cowtowncoder
Copy link
Member

First things first, try with the latest patch from the batch in question: in this case, 2.7.9.
Does the process still occur?

@prtmD
Copy link
Author

prtmD commented Feb 14, 2017

I tried with latest patch, that is 2.7.9 and also with latest version of jackson-databind 2.8.6. But it is not working still.

@oliversaggau
Copy link

oliversaggau commented May 11, 2017

Any updates on this issue? I just tested with 2.8.8 and 2.9.0-pr3, but this still throws an exception. I found an old post on Stackoverflow with the same issue.

[Edit]
Okay, I just discovered FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY DeserializationFeature. By disabled this feature, I don't get the exception.

@cowtowncoder
Copy link
Member

The problem here is this:

    private String type;

as there is no indication that this field is supposed to infer a property: it is private and has no annotations. It needs to be marked as a property; just indicating there should be one from polymorphic type id annotation is not enough.

Whether this should work without annotation is an interesting question: I can see why it would be nice; the problem however is that the way properties are introspected there is likely not enough information available to add inclusion.

@cowtowncoder cowtowncoder changed the title Deserialization not working for missing polymorphic property Polymorphic deserialization with EXTERNAL_PROPERTY fails if type property not marked as property May 11, 2017
@oliversaggau
Copy link

oliversaggau commented May 12, 2017

Ah ok, hadn't noticed the missing @JsonProperty in the OP's code. In my code I have the following code:

@JsonProperty("type")
private String type;

And I even tried adding @JsonTypeId, but both won't work.

@cowtowncoder
Copy link
Member

@oliversaggau Ok, then there seems to be some other problem.

@buremba
Copy link

buremba commented May 6, 2018

Any updates on this issue? If TypeSpecific marked as not required, there is no requirement for Jackson to try to parse the value of it.

@cowtowncoder
Copy link
Member

@buremba Well the problem is that there IS a type identifier in there, and from databinding perspective it seems like a problem -- what is that type id for? Nothing? Why would something or someone serialize type without data being typed?

So in a way I am not sure if that ought to be allowed.

@buremba
Copy link

buremba commented May 7, 2018

@cowtowncoder The type id may be useful by itself so don't assume that type id is there just for deserializing another value. For example, here is our use-case:
We have reports and each report has a type. Depending on that type, each report has options and we use different classes for different report types. We also have two different endpoints in our API server; list and get. The list reports the report names and types but not options because we just need to list the reports in a table. When the user clicks a report, we fetch the options from the server and return the data to the user.

@cowtowncoder
Copy link
Member

@buremba Ok. That makes some more sense. Although I am bit worried about potential for masking issues, I guess I can see this as valid usage esp as there is no way to indicate difference like with PROPERTY vs EXISTING_PROPERTY (former implying its pure metadata, latter that it is explicit data also used as metadata).

@cowtowncoder
Copy link
Member

Oh. I had forgotten that as per #1341 (and mentioned above), DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY can be disabled to allow such value to be missed (unless declared required).
So, @buremba, you want to disable that.

@buremba
Copy link

buremba commented May 11, 2018

@cowtowncoder Unfortunately that doesn't work. I enabled the config DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY but still get the error Missing property 'options' for external type id 'type'. I use Kotlin, Jackson 2.8.9 and the exception is thrown from ExternalTypeHandler class and line 211. Hope it helps and please reopen the issue. :)

@cowtowncoder
Copy link
Member

@buremba Ok. In that case I would need a reproduction of the problem (in plain Java) since test for #1341 passes as expected at this point.

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