Skip to content

IllegalArgumentException thrown for mismatched subclass deserialization  #2668

@nbruno

Description

@nbruno

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
}

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