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

IllegalArgumentException thrown for mismatched subclass deserialization #2668

Closed
nbruno opened this issue Mar 28, 2020 · 1 comment
Closed
Milestone

Comments

@nbruno
Copy link

nbruno commented Mar 28, 2020

Current behavior:
When TypeFactory encounters a mismatch in subtypes between the property in JSON and the subclass target value, an IllegalArgumentException is thrown.

Expected behavior:
A Jackson-specific exception is thrown that callers can handle, perhaps JsonMappingException, to indicate that the supplied JSON could not be mapped to the chosen target class.

Use case:
This causes issues when callers are dynamically invoking Jackson based on runtime information and can't easily verify if the JSON type info value matches the correct subclass. A generic IllegalArgumentException hides the fact that the supplied JSON was invalid.

One example of this is in Spring, when during content negotiation, Spring determines the subclass to deserialize into based on the Content-Type header of the request. If the user supplies a JSON payload for subclass A, but a Content-Type header that indicates subclass B, Spring will attempt to parse the JSON as subclass B, and fail with this IllegalArgumentException.

If a Jackson-specific exception was surfaced, this condition could be handled. With the current behavior, an IllegalArgumentException is too broad of an Exception to be able to handle generically.

MCVE:

public static void main(String[] args) throws IOException  {
    String json = "{\"type\": \"child2\", \"baz\":\"1\"}"; // JSON for Child2

    ObjectMapper mapper = new ObjectMapper();
    mapper.readValue(json, Child1.class); // Deserializing into Child1
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Child1.class, name = "child1"),
    @JsonSubTypes.Type(value = Child2.class, name = "child2")
})
public static class Parent {
}

public static class Child1 extends Parent {
    private String bar;
    // Getter / setter
}

public static class Child2 extends Parent {
    private String baz;
    // Getter / setter
}
@cowtowncoder
Copy link
Member

Thank you for reporting this -- yes, I agree that at very least exception type is wrong.
I think there is already another issue for allowing usage like this (but do not remember issue number offhand), where normally type id would be needed, and nominal base type as target.
But that user could give one of subtypes as valid substitute and deserialization would only fail if there is actual type mismatch (there are some other subtleties wrt whether type id would be required or not, what to do with default type, if any etc).

But first things first: I'll try to see that exception from low level is properly mapped to JsonMappingException.

@cowtowncoder cowtowncoder removed the 2.10 label Mar 29, 2020
@cowtowncoder cowtowncoder added this to the 2.11.0 milestone Mar 29, 2020
@cowtowncoder cowtowncoder changed the title IllegalArgumentException thrown for mismatched subclass deserialization IllegalArgumentException thrown for mismatched subclass deserialization Mar 29, 2020
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

2 participants