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

Incorrect target type for arrays when disabling coercion #3690

Closed
joca-bt opened this issue Dec 6, 2022 · 2 comments
Closed

Incorrect target type for arrays when disabling coercion #3690

joca-bt opened this issue Dec 6, 2022 · 2 comments

Comments

@joca-bt
Copy link

joca-bt commented Dec 6, 2022

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?

@joca-bt joca-bt added the to-evaluate Issue that has been received but not yet evaluated label Dec 6, 2022
@cowtowncoder
Copy link
Member

You are probably correct: coercion checks are more likely to be correct and exception incorrect.
One problem is that a shared set of helper methods are used for validation and they rely on type of JsonDeserializer but actual type being validated may be element type of array/List type etc.

@cowtowncoder
Copy link
Member

Looking back at the exception message, it isn't actually wrong:

Cannot coerce Integer value (1) to element of `java.util.ArrayList<java.lang.String>` 

since it specifies ELEMENT of that type (which from signature is java.lang.String).
But I think we can do better.

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