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

Fix Coercion fail message around Array and Object #3962

Original file line number Diff line number Diff line change
Expand Up @@ -1421,13 +1421,16 @@ protected final String _parseString(JsonParser p, DeserializationContext ctxt,
return ob.toString();
// 29-Jun-2020, tatu: New! "Scalar from Object" (mostly for XML)
case JsonTokenId.ID_START_OBJECT:
act = _checkObjectToStringCoercion(p, ctxt, rawTargetType);
JooHyukKim marked this conversation as resolved.
Show resolved Hide resolved
return ctxt.extractScalarFromObject(p, this, _valueClass);
JooHyukKim marked this conversation as resolved.
Show resolved Hide resolved
case JsonTokenId.ID_NUMBER_INT:
act = _checkIntToStringCoercion(p, ctxt, rawTargetType);
break;
case JsonTokenId.ID_NUMBER_FLOAT:
act = _checkFloatToStringCoercion(p, ctxt, rawTargetType);
break;
case JsonTokenId.ID_START_ARRAY:
act = _checkArrayToStringCoercion(p, ctxt, rawTargetType);
JooHyukKim marked this conversation as resolved.
Show resolved Hide resolved
case JsonTokenId.ID_TRUE:
case JsonTokenId.ID_FALSE:
act = _checkBooleanToStringCoercion(p, ctxt, rawTargetType);
Expand Down Expand Up @@ -1589,6 +1592,26 @@ protected CoercionAction _checkBooleanToStringCoercion(JsonParser p, Deserializa
return _checkToStringCoercion(p, ctxt, rawTargetType, p.getBooleanValue(), CoercionInputShape.Boolean);
}

/**
* @since 2.16
*/
protected CoercionAction _checkArrayToStringCoercion(JsonParser p, DeserializationContext ctxt,
Class<?> rawTargetType)
throws IOException
{
return _checkToStringCoercion(p, ctxt, rawTargetType, p.getText(), CoercionInputShape.Array);
}

/**
* @since 2.16
*/
protected CoercionAction _checkObjectToStringCoercion(JsonParser p, DeserializationContext ctxt,
Class<?> rawTargetType)
throws IOException
{
return _checkToStringCoercion(p, ctxt, rawTargetType, p.getText(), CoercionInputShape.Object);
}

/**
* @since 2.14
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
package com.fasterxml.jackson.databind.convert;

import java.util.List;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.cfg.CoercionAction;
import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.util.List;

public class DisableCoercions3690Test extends BaseMapTest
{
static class Input3690 {
public List<String> field;
}

static class Input3924<T> {
private T field;

public T getField() {
return field;
}

public void setField(T field) {
this.field = field;
}
}

// [databind#3690]
public void testFailMessage3690() throws Exception
{
Expand All @@ -35,4 +49,51 @@ public void testFailMessage3690() throws Exception
verifyException(e, "to `java.lang.String` value");
}
}

// [databind#3924]
public void testFailMessage3924() throws Exception {
// Arrange : Building a strict ObjectMapper.
ObjectMapper objectMapper = jsonMapperBuilder()
.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();

// Arrange : Type configuration
TypeFactory typeFactory = objectMapper.getTypeFactory();
JavaType arrayType = typeFactory.constructParametricType(List.class, String.class);
JavaType inputType = typeFactory.constructParametricType(Input3924.class, arrayType);

// Arrange : Input data
String[][] inputs = new String[][]{
new String[]{"{ \"field\": [ 1 ] }", "Cannot coerce Integer value (1)", "to `java.lang.String` value"},
new String[]{"{ \"field\": [ [ 1 ] ] }", "Cannot coerce Array value ([)", "to `java.lang.String` value"},
new String[]{"{ \"field\": [ { \"field\": 1 } ] }", "Cannot coerce Object value ({)", "to `java.lang.String` value"}
};

// Act & Assert
for (String[] input : inputs) {
_verifyFailedCoercionWithInvalidFormat(objectMapper, inputType, input);
}
}

private void _verifyFailedCoercionWithInvalidFormat(ObjectMapper objectMapper, JavaType inputType, String[] input)
JooHyukKim marked this conversation as resolved.
Show resolved Hide resolved
throws Exception
{
String jsonStr = input[0];
String inputMessage = input[1];
String targetTypeMessage = input[2];
try {
objectMapper.readValue(jsonStr, inputType);
fail("Should not pass");
} catch (InvalidFormatException e) {
assertEquals(String.class, e.getTargetType());
JooHyukKim marked this conversation as resolved.
Show resolved Hide resolved
verifyException(e, inputMessage, targetTypeMessage);
}
}
}