Incorrect target type for arrays when disabling coercion · Issue #3690 · FasterXML/jackson-databind (original) (raw)

When disabling coercions and providing a wrong type on an array element, the error message is specifying that we are trying to coerce the type of the array when it should mention we are trying to coerce the type of the element of the array. See the example below.

// Test class.
public class Input<T> {
    private final T field;

    public Input(@JsonProperty("field") T value) {
        this.field = value;
    }
}

// Building a strict ObjectMapper.
ObjectMapper objectMapper = JsonMapper.builder()
    .withCoercionConfigDefaults(config -> {
        config.setCoercion(CoercionInputShape.Boolean, CoercionAction.Fail)
            .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail)
            .setCoercion(CoercionInputShape.Float, CoercionAction.Fail)
            .setCoercion(CoercionInputShape.String, CoercionAction.Fail)
            .setCoercion(CoercionInputShape.Array, CoercionAction.Fail)
            .setCoercion(CoercionInputShape.Object, CoercionAction.Fail);
    })
    .build();
TypeFactory typeFactory = objectMapper.getTypeFactory();

JavaType arrayType = typeFactory.constructParametricType(List.class, String.class);
JavaType inputType = typeFactory.constructParametricType(Input.class, arrayType);
String json = "{ \"field\": [ 1 ] }";
objectMapper.readValue(json, inputType);

// Was expecting an error about field[0] being an integer instead of a string. Instead got the following:
-> com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot coerce Integer value (1) to element of `java.util.ArrayList<java.lang.String>` (but could if coercion was enabled using `CoercionConfig`)
 at [Source: (String)"{ "field": [ 1 ] }"; line: 1, column: 14] (through reference chain: ...$Input["field"]->java.util.ArrayList[0])
// It seems it might just be the message that is wrong? Since [0] is mentioned.

// A truly strict String parser.
public class StringDeserializer extends JsonDeserializer<String> {
    @Override
    public String deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        if (!parser.hasToken(VALUE_STRING)) {
            throw context.wrongTokenException(parser, String.class, VALUE_STRING, null);
        }

        return parser.getText();
    }
}

// If we register the StringDeserializer above in the ObjectMapper we will then get the expected error.
-> com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (VALUE_NUMBER_INT), expected VALUE_STRING
 at [Source: (String)"{ "field": [ 1 ] }"; line: 1, column: 14] (through reference chain: ...$Input["field"]->java.util.ArrayList[0])

Related to #3240.
Probably similar to #2567?