Filip Wicher
Filip Wicher

Reputation: 21

Jackson not throwing an exception on deserializing when provided json is different class type than targeted class

I have two classes A and B, both having public getters and constructors marked with @JsonCreator and @JsonProperty on constructor arguments. Both of those classes are deserialized correctly when correct json is provided. However when I provide a json that is a projection of class type A and try to deserialize it into B type object, I expect an exception to be thrown. It turnes out that jackson deserializes json correctly into B type object, but this object is just null. Is this the default behaviour? My ObjectMapper is created simply with new ObjectMapper(). Can I configure it in any way so that it throws an exception in described case?

Class A implementation:

@JsonIgnoreProperties(ignoreUnknown = true)
final class A {

    private final String propertyA;

    @JsonCreator
    A(@JsonProperty("propertyA") String propertyA) {
        this.propertyA = propertyA;
    }

    public String getPropertyA() {
        return propertyA;
    }

    @Override
    public String toString() {
        return "A{" +
            "propertyA='" + propertyA + '\'' +
            '}';
    }

}

Class B implementation:

@JsonIgnoreProperties(ignoreUnknown = true)
final class B {

    private final String propertyB;

    @JsonCreator
    B(@JsonProperty("propertyB") String propertyB) {
        this.propertyB = propertyB;
    }

    public String getPropertyB() {
        return propertyB;
    }

    @Override
    public String toString() {
        return "B{" +
            "propertyB='" + propertyB + '\'' +
            '}';
    }

}

Json with class B projection: {"propertyB":"propertyBValue"}

Deserialization code:

String jsonWithBObject = "{\"propertyB\":\"propertyBValue\"}";

A deserializedAObject = mapFromJsonToObject(jsonWithBObject, A.class);
private <T> T mapFromJsonToObject(String json, Class<T> targetClass) {
    try {
        return objectMapper.readValue(json, targetClass);
    } catch (JsonProcessingException exception) {
        throw new RuntimeException();
    }
}

And after running this code, no exception is thrown, and deserializdAObject contains: A{propertyA='null'}

Upvotes: 1

Views: 2458

Answers (2)

Smile
Smile

Reputation: 4088

@JsonIgnoreProperties(ignoreUnknown = true) is causing jackson to ignore the unknown properties and the object you get after deserialization is the one with all attributes initialised with default values (which is null for non-primitives).

Use required=true to force Jackson to throw exception in case property is missing.

 @JsonCreator
    B(@JsonProperty(value="propertyB", required=true) String propertyB) {
        this.propertyB = propertyB;
    }

Upvotes: 1

Vasily Liaskovsky
Vasily Liaskovsky

Reputation: 2538

Use @JsonProperty(required = true) to force Jackson throw exception on missing key

This property is only partially supported. Excerpt from Jackson javadoc:

 Note that as of 2.6, this property is only used for Creator
 Properties, to ensure existence of property value in JSON:
 for other properties (ones injected using a setter or mutable
 field), no validation is performed. Support for those cases
 may be added in future.

Upvotes: 2

Related Questions