aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/com/fasterxml
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/fasterxml')
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java4
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java8
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceContainersTest.java175
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java255
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceFloatToIntTest.java298
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceJDKScalarsTest.java (renamed from src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java)60
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceMiscScalarsTest.java281
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoercePojosTest.java188
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceToBooleanTest.java273
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java84
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java4
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/TestMapConversions.java6
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java78
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeserFailOnUnknown2719Test.java52
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2118Test.java (renamed from src/test/java/com/fasterxml/jackson/failing/PropertyAccessReadOnly2118Test.java)21
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2283Test.java (renamed from src/test/java/com/fasterxml/jackson/failing/ReadOnlyList2283Test.java)4
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java97
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java20
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderErrorHandling.java14
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderFailTest.java3
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithTypeParametersTest.java (renamed from src/test/java/com/fasterxml/jackson/failing/BuilderDeserializationTest921.java)43
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java26
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java52
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java37
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/ArrayDeserializationTest.java (renamed from src/test/java/com/fasterxml/jackson/databind/deser/TestArrayDeserialization.java)4
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java65
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKScalarsTest.java152
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java25
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapWithGenericValuesDeserTest.java (renamed from src/test/java/com/fasterxml/jackson/databind/deser/TestGenericMapDeser.java)4
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/jdk/VoidProperties2675Test.java61
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/interop/DateJava8FallbacksTest.java45
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/jsontype/TestMultipleTypeNames.java136
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java24
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java53
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java7
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java151
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java27
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java9
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java27
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java49
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/JDKNumberDeser2644Test.java86
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java2
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/ParsingContextExtTypeId2747Test.java65
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java50
-rw-r--r--src/test/java/com/fasterxml/jackson/failing/VoidProperties2675Test.java25
55 files changed, 2450 insertions, 720 deletions
diff --git a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
index 549e96028..13aca9c95 100644
--- a/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/BaseMapTest.java
@@ -359,6 +359,10 @@ public abstract class BaseMapTest
return json.replace("'", "\"");
}
+ protected static String a2q(String json) {
+ return json.replace("'", "\"");
+ }
+
protected static String quotesToApos(String json) {
return json.replace("\"", "'");
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
index 7e39256c5..9d84df29a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ObjectMapperTest.java
@@ -272,7 +272,6 @@ public class ObjectMapperTest extends BaseMapTest
assertTrue(dc.shouldSortPropertiesAlphabetically());
}
-
public void testJsonFactoryLinkage()
{
// first, implicit factory, giving implicit linkage
@@ -363,6 +362,13 @@ public class ObjectMapperTest extends BaseMapTest
.canSerialize(EmptyBean.class));
}
+ // for [databind#2749]: just to check there's no NPE; method really not useful
+ public void testCanDeserialize()
+ {
+ assertTrue(MAPPER.canDeserialize(MAPPER.constructType(EmptyBean.class)));
+ assertTrue(MAPPER.canDeserialize(MAPPER.constructType(Object.class)));
+ }
+
// for [databind#898]
public void testSerializerProviderAccess() throws Exception
{
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoerceContainersTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceContainersTest.java
new file mode 100644
index 000000000..163588155
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceContainersTest.java
@@ -0,0 +1,175 @@
+package com.fasterxml.jackson.databind.convert;
+
+import java.util.*;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+
+import com.fasterxml.jackson.databind.cfg.CoercionAction;
+import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
+
+public class CoerceContainersTest extends BaseMapTest
+{
+ private final String JSON_EMPTY = quote("");
+
+ private final ObjectMapper VANILLA_MAPPER = sharedMapper();
+
+ private final ObjectMapper COERCING_MAPPER = newJsonMapper();
+ {
+ COERCING_MAPPER.coercionConfigDefaults().setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
+ }
+
+ /*
+ /********************************************************
+ /* Tests for collections
+ /********************************************************
+ */
+
+ public void testScalarCollections() throws Exception
+ {
+ final JavaType listType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<List<Double>>() { });
+ _verifyNoCoercion(listType);
+ List<Double> result = _readWithCoercion(listType);
+ assertNotNull(result);
+ assertEquals(0, result.size());
+ }
+
+ public void testStringCollections() throws Exception
+ {
+ final JavaType listType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<List<String>>() { });
+ _verifyNoCoercion(listType);
+ List<String> result = _readWithCoercion(listType);
+ assertNotNull(result);
+ assertEquals(0, result.size());
+ }
+
+ /*
+ /********************************************************
+ /* Tests for Maps
+ /********************************************************
+ */
+
+ public void testScalarMap() throws Exception
+ {
+ final JavaType mapType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<Map<Long, Boolean>>() { });
+ _verifyNoCoercion(mapType);
+ Map<?,?> result = _readWithCoercion(mapType);
+ assertNotNull(result);
+ assertEquals(0, result.size());
+ }
+
+ public void testEnumMap() throws Exception
+ {
+ final JavaType mapType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<EnumMap<ABC, Boolean>>() { });
+ _verifyNoCoercion(mapType);
+ Map<?,?> result = _readWithCoercion(mapType);
+ assertNotNull(result);
+ assertEquals(0, result.size());
+ }
+
+ /*
+ /********************************************************
+ /* Tests for arrays
+ /********************************************************
+ */
+
+ public void testObjectArray() throws Exception
+ {
+ final JavaType arrayType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<Object[]>() { });
+ _verifyNoCoercion(arrayType);
+ Object[] result = _readWithCoercion(arrayType);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testStringArray() throws Exception
+ {
+ final JavaType arrayType = VANILLA_MAPPER.getTypeFactory()
+ .constructType(new TypeReference<String[]>() { });
+ _verifyNoCoercion(arrayType);
+ String[] result = _readWithCoercion(arrayType);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testBooleanArray() throws Exception
+ {
+ _verifyNoCoercion(boolean[].class);
+ boolean[] result = _readWithCoercion(boolean[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testIntArray() throws Exception
+ {
+ _verifyNoCoercion(int[].class);
+ int[] result = _readWithCoercion(int[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testLongArray() throws Exception
+ {
+ _verifyNoCoercion(long[].class);
+ long[] result = _readWithCoercion(long[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testFloatArray() throws Exception
+ {
+ _verifyNoCoercion(float[].class);
+ float[] result = _readWithCoercion(float[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testDoubleArray() throws Exception
+ {
+ _verifyNoCoercion(double[].class);
+ double[] result = _readWithCoercion(double[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ public void testPOJOArray() throws Exception
+ {
+ _verifyNoCoercion(StringWrapper[].class);
+ StringWrapper[] result = _readWithCoercion(StringWrapper[].class);
+ assertNotNull(result);
+ assertEquals(0, result.length);
+ }
+
+ /*
+ /********************************************************
+ /* Helper methods
+ /********************************************************
+ */
+
+ private void _verifyNoCoercion(Class<?> targetType) throws Exception {
+ _verifyNoCoercion(VANILLA_MAPPER.constructType(targetType));
+ }
+
+ private void _verifyNoCoercion(JavaType targetType) throws Exception {
+ try {
+ VANILLA_MAPPER.readerFor(targetType).readValue(JSON_EMPTY);
+ fail("Should not pass");
+ } catch (Exception e) {
+ verifyException(e, "Cannot deserialize value of type");
+ verifyException(e, "from empty String");
+ }
+ }
+
+ private <T> T _readWithCoercion(Class<?> targetType) throws Exception {
+ return COERCING_MAPPER.readerFor(targetType).readValue(JSON_EMPTY);
+ }
+
+ private <T> T _readWithCoercion(JavaType targetType) throws Exception {
+ return COERCING_MAPPER.readerFor(targetType).readValue(JSON_EMPTY);
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java
new file mode 100644
index 000000000..ff429b8ae
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java
@@ -0,0 +1,255 @@
+package com.fasterxml.jackson.databind.convert;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URL;
+import java.util.*;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.CoercionAction;
+import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.type.LogicalType;
+
+/**
+ * Tests to verify implementation of [databind#540]; also for
+ * follow up work of:
+ *
+ * - [databind#994]
+ */
+public class CoerceEmptyArrayTest extends BaseMapTest
+{
+ private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
+ private final ObjectReader DEFAULT_READER = DEFAULT_MAPPER.reader();
+ private final ObjectReader READER_WITH_ARRAYS = DEFAULT_READER
+ .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
+
+ private final ObjectMapper MAPPER_TO_EMPTY;
+ {
+ MAPPER_TO_EMPTY = newJsonMapper();
+ MAPPER_TO_EMPTY.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.AsEmpty);
+ }
+
+ private final ObjectMapper MAPPER_TRY_CONVERT;
+ {
+ MAPPER_TRY_CONVERT = newJsonMapper();
+ MAPPER_TRY_CONVERT.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.TryConvert);
+ }
+
+ private final ObjectMapper MAPPER_TO_NULL;
+ {
+ MAPPER_TO_NULL = newJsonMapper();
+ MAPPER_TO_NULL.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.AsNull);
+ }
+
+ private final ObjectMapper MAPPER_TO_FAIL;
+ {
+ MAPPER_TO_FAIL = newJsonMapper();
+ MAPPER_TO_FAIL.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.Fail);
+ }
+
+ static class Bean {
+ public String a = "foo";
+
+ @Override
+ public boolean equals(Object o) {
+ return (o instanceof Bean)
+ && a.equals(((Bean) o).a);
+ }
+ }
+
+ final static String EMPTY_ARRAY = " [\n]";
+
+ /*
+ /**********************************************************
+ /* Test methods, settings
+ /**********************************************************
+ */
+
+ public void testSettings() {
+ assertFalse(DEFAULT_MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+ assertFalse(DEFAULT_READER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+ assertTrue(READER_WITH_ARRAYS.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
+ }
+
+ /*
+ /**********************************************************
+ /* Test methods, POJOs
+ /**********************************************************
+ */
+
+ // [databind#540]
+ public void testPOJOFromEmptyArray() throws Exception
+ {
+ final Class<?> targetType = Bean.class;
+
+ _verifyFailForEmptyArray(DEFAULT_READER, targetType);
+ _verifyFailForEmptyArray(MAPPER_TO_FAIL, targetType);
+
+ // Nulls for explicit, "TryConvert"
+ _verifyToNullCoercion(MAPPER_TO_NULL, targetType);
+ _verifyToNullCoercion(MAPPER_TRY_CONVERT, targetType);
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, targetType, new Bean());
+
+ // But let's also check precedence: legacy setting allow, but mask for type
+ ObjectMapper mapper = jsonMapperBuilder()
+ .enable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)
+ .build();
+ mapper.coercionConfigFor(targetType)
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.Fail);
+ _verifyFailForEmptyArray(mapper, targetType);
+
+ // and conversely
+ mapper = jsonMapperBuilder()
+ .disable(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT)
+ .build();
+ mapper.coercionConfigFor(LogicalType.POJO)
+ .setCoercion(CoercionInputShape.EmptyArray, CoercionAction.AsEmpty);
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, targetType, new Bean());
+ }
+
+ /*
+ /**********************************************************
+ /* Test methods, Maps
+ /**********************************************************
+ */
+
+ public void testMapFromEmptyArray() throws Exception
+ {
+ final Class<?> targetType = Map.class;
+
+ _verifyFailForEmptyArray(DEFAULT_READER, targetType);
+ _verifyFailForEmptyArray(MAPPER_TO_FAIL, targetType);
+
+ // Nulls for explicit, "TryConvert"
+ _verifyToNullCoercion(MAPPER_TO_NULL, targetType);
+ _verifyToNullCoercion(MAPPER_TRY_CONVERT, targetType);
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, targetType, new LinkedHashMap<>());
+
+ // assume overrides work ok since POJOs test it
+ }
+
+ public void testEnumMapFromEmptyArray() throws Exception
+ {
+ final JavaType targetType = DEFAULT_READER.getTypeFactory()
+ .constructType(new TypeReference<EnumMap<ABC,String>>() { });
+
+ assertNull(MAPPER_TO_NULL.readerFor(targetType).readValue(EMPTY_ARRAY));
+
+ EnumMap<?,?> result = MAPPER_TO_EMPTY.readerFor(targetType).readValue(EMPTY_ARRAY);
+ assertNotNull(result);
+ assertTrue(result.isEmpty());
+ }
+
+ /*
+ /**********************************************************
+ /* Test methods, scalars
+ /**********************************************************
+ */
+
+ public void testNumbersFromEmptyArray() throws Exception
+ {
+ for (Class<?> targetType : new Class<?>[] {
+ Boolean.class, Character.class,
+ Byte.class, Short.class, Integer.class, Long.class,
+ Float.class, Double.class,
+ BigInteger.class, BigDecimal.class
+ }) {
+ // Default, fail; explicit fail
+ _verifyFailForEmptyArray(DEFAULT_READER, targetType);
+ _verifyFailForEmptyArray(MAPPER_TO_FAIL, targetType);
+
+ // Nulls for explicit, "TryConvert"
+ _verifyToNullCoercion(MAPPER_TO_NULL, targetType);
+ _verifyToNullCoercion(MAPPER_TRY_CONVERT, targetType);
+ }
+
+ // But as-empty needs separate
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Boolean.class, Boolean.FALSE);
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Character.class, Character.valueOf('\0'));
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Byte.class, Byte.valueOf((byte) 0));
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Short.class, Short.valueOf((short) 0));
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Integer.class, Integer.valueOf(0));
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Long.class, Long.valueOf(0L));
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Float.class, Float.valueOf(0f));
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, Double.class, Double.valueOf(0d));
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, BigInteger.class, BigInteger.ZERO);
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, BigDecimal.class, new BigDecimal(BigInteger.ZERO));
+ }
+
+ public void testOtherScalarsFromEmptyArray() throws Exception
+ {
+ for (Class<?> targetType : new Class<?>[] {
+ String.class, StringBuilder.class,
+ UUID.class, URL.class, URI.class,
+ Date.class, Calendar.class
+ }) {
+ _verifyFailForEmptyArray(DEFAULT_READER, targetType);
+ _verifyFailForEmptyArray(MAPPER_TO_FAIL, targetType);
+
+ // Nulls for explicit, "TryConvert"
+ _verifyToNullCoercion(MAPPER_TO_NULL, targetType);
+ _verifyToNullCoercion(MAPPER_TRY_CONVERT, targetType);
+ }
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, String.class, "");
+ StringBuilder sb = MAPPER_TO_EMPTY.readerFor(StringBuilder.class)
+ .readValue(EMPTY_ARRAY);
+ assertEquals(0, sb.length());
+
+ _verifyToEmptyCoercion(MAPPER_TO_EMPTY, UUID.class, new UUID(0L, 0L));
+ }
+
+ /*
+ /**********************************************************
+ /* Helper methods
+ /**********************************************************
+ */
+
+ private void _verifyToNullCoercion(ObjectMapper mapper, Class<?> cls) throws Exception {
+ _verifyToNullCoercion(mapper.reader(), cls);
+ }
+
+ private void _verifyToNullCoercion(ObjectReader r, Class<?> cls) throws Exception {
+ Object result = r.forType(cls).readValue(EMPTY_ARRAY);
+ if (result != null) {
+ fail("Expect null for "+cls.getName()+", got: "+result);
+ }
+ }
+
+ private void _verifyToEmptyCoercion(ObjectMapper mapper, Class<?> cls, Object exp) throws Exception {
+ _verifyToEmptyCoercion(mapper.reader(), cls, exp);
+ }
+
+ private void _verifyToEmptyCoercion(ObjectReader r, Class<?> cls, Object exp) throws Exception {
+ Object result = r.forType(cls).readValue(EMPTY_ARRAY);
+ if (!exp.equals(result)) {
+ fail("Expect value ["+exp+"] for "+cls.getName()+", got: "+result);
+ }
+ }
+
+ private void _verifyFailForEmptyArray(ObjectMapper mapper, Class<?> targetType) throws Exception {
+ _verifyFailForEmptyArray(mapper.readerFor(targetType), targetType);
+ }
+
+ private void _verifyFailForEmptyArray(ObjectReader r, Class<?> targetType) throws Exception
+ {
+ try {
+ r.forType(targetType).readValue(EMPTY_ARRAY);
+ fail("Should not accept Empty Array for "+targetType.getName()+" by default");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoerceFloatToIntTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceFloatToIntTest.java
new file mode 100644
index 000000000..5bf27e405
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceFloatToIntTest.java
@@ -0,0 +1,298 @@
+package com.fasterxml.jackson.databind.convert;
+
+import java.math.BigInteger;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.CoercionAction;
+import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.type.LogicalType;
+
+public class CoerceFloatToIntTest extends BaseMapTest
+{
+ private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
+ private final ObjectReader READER_LEGACY_FAIL = DEFAULT_MAPPER.reader()
+ .without(DeserializationFeature.ACCEPT_FLOAT_AS_INT);
+
+ private final ObjectMapper MAPPER_TO_EMPTY; {
+ MAPPER_TO_EMPTY = newJsonMapper();
+ MAPPER_TO_EMPTY.coercionConfigFor(LogicalType.Integer)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.AsEmpty);
+ }
+
+ private final ObjectMapper MAPPER_TRY_CONVERT; {
+ MAPPER_TRY_CONVERT = newJsonMapper();
+ MAPPER_TRY_CONVERT.coercionConfigFor(LogicalType.Integer)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.TryConvert);
+ }
+
+ private final ObjectMapper MAPPER_TO_NULL; {
+ MAPPER_TO_NULL = newJsonMapper();
+ MAPPER_TO_NULL.coercionConfigFor(LogicalType.Integer)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.AsNull);
+ }
+
+ private final ObjectMapper MAPPER_TO_FAIL; {
+ MAPPER_TO_FAIL = newJsonMapper();
+ MAPPER_TO_FAIL.coercionConfigFor(LogicalType.Integer)
+ .setCoercion(CoercionInputShape.Float, CoercionAction.Fail);
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, defaults (legacy)
+ /********************************************************
+ */
+
+ public void testLegacyDoubleToIntCoercion() throws Exception
+ {
+ // by default, should be ok
+ Integer I = DEFAULT_MAPPER.readValue(" 1.25 ", Integer.class);
+ assertEquals(1, I.intValue());
+ {
+ IntWrapper w = DEFAULT_MAPPER.readValue("{\"i\":-2.25 }", IntWrapper.class);
+ assertEquals(-2, w.i);
+ int[] arr = DEFAULT_MAPPER.readValue("[ 1.25 ]", int[].class);
+ assertEquals(1, arr[0]);
+ }
+
+ Long L = DEFAULT_MAPPER.readValue(" 3.33 ", Long.class);
+ assertEquals(3L, L.longValue());
+ {
+ LongWrapper w = DEFAULT_MAPPER.readValue("{\"l\":-2.25 }", LongWrapper.class);
+ assertEquals(-2L, w.l);
+ long[] arr = DEFAULT_MAPPER.readValue("[ 1.25 ]", long[].class);
+ assertEquals(1, arr[0]);
+ }
+
+ Short S = DEFAULT_MAPPER.readValue("42.33", Short.class);
+ assertEquals(42, S.intValue());
+
+ BigInteger biggie = DEFAULT_MAPPER.readValue("95.3", BigInteger.class);
+ assertEquals(95L, biggie.longValue());
+ }
+
+ public void testLegacyFailDoubleToInt() throws Exception
+ {
+ _verifyCoerceFail(READER_LEGACY_FAIL, Integer.class, "1.5", "java.lang.Integer");
+ _verifyCoerceFail(READER_LEGACY_FAIL, Integer.TYPE, "1.5", "int");
+ _verifyCoerceFail(READER_LEGACY_FAIL, IntWrapper.class, "{\"i\":-2.25 }", "int");
+ _verifyCoerceFail(READER_LEGACY_FAIL, int[].class, "[ 2.5 ]", "element of `int[]`");
+ }
+
+ public void testLegacyFailDoubleToLong() throws Exception
+ {
+ _verifyCoerceFail(READER_LEGACY_FAIL, Long.class, "0.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, Long.TYPE, "-2.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, LongWrapper.class, "{\"l\": 7.7 }");
+ _verifyCoerceFail(READER_LEGACY_FAIL, long[].class, "[ -1.35 ]", "element of `long[]`");
+ }
+
+ public void testLegacyFailDoubleToOther() throws Exception
+ {
+ _verifyCoerceFail(READER_LEGACY_FAIL, Short.class, "0.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, Short.TYPE, "-2.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, short[].class, "[ -1.35 ]", "element of `short[]`");
+
+ _verifyCoerceFail(READER_LEGACY_FAIL, Byte.class, "0.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, Byte.TYPE, "-2.5");
+ _verifyCoerceFail(READER_LEGACY_FAIL, byte[].class, "[ -1.35 ]", "element of `byte[]`");
+
+ _verifyCoerceFail(READER_LEGACY_FAIL, BigInteger.class, "25236.256");
+
+ // 13-Jun-2020, tatu: No explicit deserializer for `AtomicLong` yet
+// _verifyCoerceFail(READER_LEGACY_FAIL, AtomicLong.class, "25236.256");
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, CoerceConfig, to null
+ /********************************************************
+ */
+
+ public void testCoerceConfigFloatToNull() throws Exception
+ {
+ assertNull(MAPPER_TO_NULL.readValue("1.5", Integer.class));
+ // `null` not possible for primitives, must use empty (aka default) value
+ assertEquals(Integer.valueOf(0), MAPPER_TO_NULL.readValue("1.5", Integer.TYPE));
+ {
+ IntWrapper w = MAPPER_TO_NULL.readValue( "{\"i\":-2.25 }", IntWrapper.class);
+ assertEquals(0, w.i);
+ int[] ints = MAPPER_TO_NULL.readValue("[ 2.5 ]", int[].class);
+ assertEquals(1, ints.length);
+ assertEquals(0, ints[0]);
+ }
+
+ assertNull(MAPPER_TO_NULL.readValue("2.5", Long.class));
+ assertEquals(Long.valueOf(0L), MAPPER_TO_NULL.readValue("-4.25", Long.TYPE));
+ {
+ LongWrapper w = MAPPER_TO_NULL.readValue( "{\"l\":-2.25 }", LongWrapper.class);
+ assertEquals(0L, w.l);
+ long[] l = MAPPER_TO_NULL.readValue("[ 2.5 ]", long[].class);
+ assertEquals(1, l.length);
+ assertEquals(0L, l[0]);
+ }
+
+ assertNull(MAPPER_TO_NULL.readValue("2.5", Short.class));
+ assertEquals(Short.valueOf((short) 0), MAPPER_TO_NULL.readValue("-4.25", Short.TYPE));
+ {
+ short[] s = MAPPER_TO_NULL.readValue("[ 2.5 ]", short[].class);
+ assertEquals(1, s.length);
+ assertEquals((short) 0, s[0]);
+ }
+
+ assertNull(MAPPER_TO_NULL.readValue("2.5", Byte.class));
+ assertEquals(Byte.valueOf((byte) 0), MAPPER_TO_NULL.readValue("-4.25", Byte.TYPE));
+ {
+ byte[] arr = MAPPER_TO_NULL.readValue("[ 2.5 ]", byte[].class);
+ assertEquals(1, arr.length);
+ assertEquals((byte) 0, arr[0]);
+ }
+
+ assertNull(MAPPER_TO_NULL.readValue("2.5", BigInteger.class));
+ {
+ BigInteger[] arr = MAPPER_TO_NULL.readValue("[ 2.5 ]", BigInteger[].class);
+ assertEquals(1, arr.length);
+ assertNull(arr[0]);
+ }
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, CoerceConfig, to empty
+ /********************************************************
+ */
+
+ public void testCoerceConfigFloatToEmpty() throws Exception
+ {
+ assertEquals(Integer.valueOf(0), MAPPER_TO_EMPTY.readValue("1.2", Integer.class));
+ assertEquals(Integer.valueOf(0), MAPPER_TO_EMPTY.readValue("1.5", Integer.TYPE));
+ {
+ IntWrapper w = MAPPER_TO_EMPTY.readValue( "{\"i\":-2.25 }", IntWrapper.class);
+ assertEquals(0, w.i);
+ int[] ints = MAPPER_TO_EMPTY.readValue("[ 2.5 ]", int[].class);
+ assertEquals(1, ints.length);
+ assertEquals(0, ints[0]);
+ }
+
+ assertEquals(Long.valueOf(0), MAPPER_TO_EMPTY.readValue("1.2", Long.class));
+ assertEquals(Long.valueOf(0), MAPPER_TO_EMPTY.readValue("1.5", Long.TYPE));
+ {
+ LongWrapper w = MAPPER_TO_EMPTY.readValue( "{\"l\":-2.25 }", LongWrapper.class);
+ assertEquals(0L, w.l);
+ long[] l = MAPPER_TO_EMPTY.readValue("[ 2.5 ]", long[].class);
+ assertEquals(1, l.length);
+ assertEquals(0L, l[0]);
+ }
+
+ assertEquals(Short.valueOf((short)0), MAPPER_TO_EMPTY.readValue("1.2", Short.class));
+ assertEquals(Short.valueOf((short) 0), MAPPER_TO_EMPTY.readValue("1.5", Short.TYPE));
+
+ assertEquals(Byte.valueOf((byte)0), MAPPER_TO_EMPTY.readValue("1.2", Byte.class));
+ assertEquals(Byte.valueOf((byte) 0), MAPPER_TO_EMPTY.readValue("1.5", Byte.TYPE));
+
+ assertEquals(BigInteger.valueOf(0L), MAPPER_TO_EMPTY.readValue("124.5", BigInteger.class));
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, CoerceConfig, coerce
+ /********************************************************
+ */
+
+ public void testCoerceConfigFloatSuccess() throws Exception
+ {
+ assertEquals(Integer.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.2", Integer.class));
+ assertEquals(Integer.valueOf(3), MAPPER_TRY_CONVERT.readValue("3.4", Integer.TYPE));
+ {
+ IntWrapper w = MAPPER_TRY_CONVERT.readValue( "{\"i\":-2.25 }", IntWrapper.class);
+ assertEquals(-2, w.i);
+ int[] ints = MAPPER_TRY_CONVERT.readValue("[ 22.10 ]", int[].class);
+ assertEquals(1, ints.length);
+ assertEquals(22, ints[0]);
+ }
+
+ assertEquals(Long.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.2", Long.class));
+ assertEquals(Long.valueOf(1), MAPPER_TRY_CONVERT.readValue("1.5", Long.TYPE));
+ {
+ LongWrapper w = MAPPER_TRY_CONVERT.readValue( "{\"l\":-2.25 }", LongWrapper.class);
+ assertEquals(-2L, w.l);
+ long[] l = MAPPER_TRY_CONVERT.readValue("[ 2.2 ]", long[].class);
+ assertEquals(1, l.length);
+ assertEquals(2L, l[0]);
+ }
+
+ assertEquals(Short.valueOf((short)1), MAPPER_TRY_CONVERT.readValue("1.2", Short.class));
+ assertEquals(Short.valueOf((short) 19), MAPPER_TRY_CONVERT.readValue("19.2", Short.TYPE));
+
+ assertEquals(Byte.valueOf((byte)1), MAPPER_TRY_CONVERT.readValue("1.2", Byte.class));
+ assertEquals(Byte.valueOf((byte) 1), MAPPER_TRY_CONVERT.readValue("1.5", Byte.TYPE));
+
+ assertEquals(BigInteger.valueOf(124L), MAPPER_TRY_CONVERT.readValue("124.2", BigInteger.class));
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, CoerceConfig, fail
+ /********************************************************
+ */
+
+ public void testCoerceConfigFailFromFloat() throws Exception
+ {
+ _verifyCoerceFail(MAPPER_TO_FAIL, Integer.class, "1.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, Integer.TYPE, "1.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, IntWrapper.class, "{\"i\":-2.25 }", "int");
+ _verifyCoerceFail(MAPPER_TO_FAIL, int[].class, "[ 2.5 ]", "element of `int[]`");
+
+ _verifyCoerceFail(MAPPER_TO_FAIL, Long.class, "0.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, Long.TYPE, "-2.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, LongWrapper.class, "{\"l\": 7.7 }");
+ _verifyCoerceFail(MAPPER_TO_FAIL, long[].class, "[ -1.35 ]", "element of `long[]`");
+
+ _verifyCoerceFail(MAPPER_TO_FAIL, Short.class, "0.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, Short.TYPE, "-2.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, short[].class, "[ -1.35 ]", "element of `short[]`");
+
+ _verifyCoerceFail(MAPPER_TO_FAIL, Byte.class, "0.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, Byte.TYPE, "-2.5");
+ _verifyCoerceFail(MAPPER_TO_FAIL, byte[].class, "[ -1.35 ]", "element of `byte[]`");
+
+ _verifyCoerceFail(MAPPER_TO_FAIL, BigInteger.class, "25236.256");
+ }
+
+ /*
+ /********************************************************
+ /* Helper methods
+ /********************************************************
+ */
+
+ private void _verifyCoerceFail(ObjectMapper m, Class<?> targetType,
+ String doc) throws Exception
+ {
+ _verifyCoerceFail(m.reader(), targetType, doc, targetType.getName());
+ }
+
+ private void _verifyCoerceFail(ObjectMapper m, Class<?> targetType,
+ String doc, String targetTypeDesc) throws Exception
+ {
+ _verifyCoerceFail(m.reader(), targetType, doc, targetTypeDesc);
+ }
+
+ private void _verifyCoerceFail(ObjectReader r, Class<?> targetType,
+ String doc) throws Exception
+ {
+ _verifyCoerceFail(r, targetType, doc, targetType.getName());
+ }
+
+ private void _verifyCoerceFail(ObjectReader r, Class<?> targetType,
+ String doc, String targetTypeDesc) throws Exception
+ {
+ try {
+ r.forType(targetType).readValue(doc);
+ fail("Should not accept Float for "+targetType.getName()+" by default");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "Cannot coerce Floating-point");
+ verifyException(e, targetTypeDesc);
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceJDKScalarsTest.java
index 0a20c7626..0fbade77e 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/ScalarCoercionTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceJDKScalarsTest.java
@@ -1,20 +1,22 @@
-package com.fasterxml.jackson.databind.struct;
+package com.fasterxml.jackson.databind.convert;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.util.concurrent.atomic.AtomicBoolean;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
-public class ScalarCoercionTest extends BaseMapTest
+// Tests for "old" coercions (pre-2.12), with `MapperFeature.ALLOW_COERCION_OF_SCALARS`
+public class CoerceJDKScalarsTest extends BaseMapTest
{
static class BooleanPOJO {
- public boolean value;
+ public Boolean value;
}
private final ObjectMapper COERCING_MAPPER = jsonMapperBuilder()
@@ -55,6 +57,7 @@ public class ScalarCoercionTest extends BaseMapTest
_verifyNullOkFromEmpty(BigInteger.class, null);
_verifyNullOkFromEmpty(BigDecimal.class, null);
+ _verifyNullOkFromEmpty(AtomicBoolean.class, null);
}
private void _verifyNullOkFromEmpty(Class<?> type, Object exp) throws IOException
@@ -91,6 +94,7 @@ public class ScalarCoercionTest extends BaseMapTest
_verifyNullFail(BigInteger.class);
_verifyNullFail(BigDecimal.class);
+ _verifyNullFail(AtomicBoolean.class);
}
private void _verifyNullFail(Class<?> type) throws IOException
@@ -100,7 +104,6 @@ public class ScalarCoercionTest extends BaseMapTest
fail("Should have failed for "+type);
} catch (MismatchedInputException e) {
verifyException(e, "Cannot coerce empty String");
- verifyException(e, "Null value for");
}
}
@@ -110,7 +113,7 @@ public class ScalarCoercionTest extends BaseMapTest
/**********************************************************
*/
- public void testStringCoercionOk() throws Exception
+ public void testStringCoercionOkBoolean() throws Exception
{
// first successful coercions. Boolean has a ton...
_verifyCoerceSuccess("1", Boolean.TYPE, Boolean.TRUE);
@@ -119,13 +122,20 @@ public class ScalarCoercionTest extends BaseMapTest
_verifyCoerceSuccess(quote("true"), Boolean.class, Boolean.TRUE);
_verifyCoerceSuccess(quote("True"), Boolean.TYPE, Boolean.TRUE);
_verifyCoerceSuccess(quote("True"), Boolean.class, Boolean.TRUE);
+ _verifyCoerceSuccess(quote("TRUE"), Boolean.TYPE, Boolean.TRUE);
+ _verifyCoerceSuccess(quote("TRUE"), Boolean.class, Boolean.TRUE);
_verifyCoerceSuccess("0", Boolean.TYPE, Boolean.FALSE);
_verifyCoerceSuccess("0", Boolean.class, Boolean.FALSE);
_verifyCoerceSuccess(quote("false"), Boolean.TYPE, Boolean.FALSE);
_verifyCoerceSuccess(quote("false"), Boolean.class, Boolean.FALSE);
_verifyCoerceSuccess(quote("False"), Boolean.TYPE, Boolean.FALSE);
_verifyCoerceSuccess(quote("False"), Boolean.class, Boolean.FALSE);
+ _verifyCoerceSuccess(quote("FALSE"), Boolean.TYPE, Boolean.FALSE);
+ _verifyCoerceSuccess(quote("FALSE"), Boolean.class, Boolean.FALSE);
+ }
+ public void testStringCoercionOkNumbers() throws Exception
+ {
_verifyCoerceSuccess(quote("123"), Byte.TYPE, Byte.valueOf((byte) 123));
_verifyCoerceSuccess(quote("123"), Byte.class, Byte.valueOf((byte) 123));
_verifyCoerceSuccess(quote("123"), Short.TYPE, Short.valueOf((short) 123));
@@ -141,12 +151,27 @@ public class ScalarCoercionTest extends BaseMapTest
_verifyCoerceSuccess(quote("123"), BigInteger.class, BigInteger.valueOf(123));
_verifyCoerceSuccess(quote("123.0"), BigDecimal.class, new BigDecimal("123.0"));
+
+ AtomicBoolean ab = COERCING_MAPPER.readValue(quote("true"), AtomicBoolean.class);
+ assertNotNull(ab);
+ assertTrue(ab.get());
}
- public void testStringCoercionFail() throws Exception
+ public void testStringCoercionFailBoolean() throws Exception
{
_verifyRootStringCoerceFail("true", Boolean.TYPE);
_verifyRootStringCoerceFail("true", Boolean.class);
+ _verifyRootStringCoerceFail("True", Boolean.TYPE);
+ _verifyRootStringCoerceFail("True", Boolean.class);
+ _verifyRootStringCoerceFail("TRUE", Boolean.TYPE);
+ _verifyRootStringCoerceFail("TRUE", Boolean.class);
+
+ _verifyRootStringCoerceFail("false", Boolean.TYPE);
+ _verifyRootStringCoerceFail("false", Boolean.class);
+ }
+
+ public void testStringCoercionFailInteger() throws Exception
+ {
_verifyRootStringCoerceFail("123", Byte.TYPE);
_verifyRootStringCoerceFail("123", Byte.class);
_verifyRootStringCoerceFail("123", Short.TYPE);
@@ -155,6 +180,10 @@ public class ScalarCoercionTest extends BaseMapTest
_verifyRootStringCoerceFail("123", Integer.class);
_verifyRootStringCoerceFail("123", Long.TYPE);
_verifyRootStringCoerceFail("123", Long.class);
+ }
+
+ public void testStringCoercionFailFloat() throws Exception
+ {
_verifyRootStringCoerceFail("123.5", Float.TYPE);
_verifyRootStringCoerceFail("123.5", Float.class);
_verifyRootStringCoerceFail("123.5", Double.TYPE);
@@ -192,8 +221,10 @@ public class ScalarCoercionTest extends BaseMapTest
{
// And then we have coercions from more esoteric types too
- _verifyCoerceFail("65", Character.class);
- _verifyCoerceFail("65", Character.TYPE);
+ _verifyCoerceFail("65", Character.class,
+ "Cannot coerce Integer value (65) to `java.lang.Character` value");
+ _verifyCoerceFail("65", Character.TYPE,
+ "Cannot coerce Integer value (65) to `char` value");
}
/*
@@ -209,16 +240,15 @@ public class ScalarCoercionTest extends BaseMapTest
assertEquals(exp, result);
}
- private void _verifyCoerceFail(String input, Class<?> type) throws IOException
+ private void _verifyCoerceFail(String input, Class<?> type,
+ String... expMatches) throws IOException
{
try {
NOT_COERCING_MAPPER.readerFor(type)
.readValue(input);
fail("Should not have allowed coercion");
} catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce ");
- verifyException(e, " for type `");
- verifyException(e, "enable `MapperFeature.ALLOW_COERCION_OF_SCALARS` to allow");
+ verifyException(e, expMatches);
}
}
@@ -245,8 +275,8 @@ public class ScalarCoercionTest extends BaseMapTest
fail("Should not have allowed coercion");
} catch (MismatchedInputException e) {
verifyException(e, "Cannot coerce ");
- verifyException(e, " for type `");
- verifyException(e, "enable `MapperFeature.ALLOW_COERCION_OF_SCALARS` to allow");
+ verifyException(e, " to `");
+ verifyException(e, "` value");
assertNotNull(e.getProcessor());
assertSame(p, e.getProcessor());
@@ -282,7 +312,7 @@ public class ScalarCoercionTest extends BaseMapTest
JsonToken tokenType, String tokenValue) throws IOException
{
// 2 different possibilities here
- verifyException(e, "Cannot coerce Number", "Cannot deserialize instance of `");
+ verifyException(e, "Cannot coerce Integer value", "Cannot deserialize value of type `");
JsonParser p = (JsonParser) e.getProcessor();
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoerceMiscScalarsTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceMiscScalarsTest.java
new file mode 100644
index 000000000..405dd35e3
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceMiscScalarsTest.java
@@ -0,0 +1,281 @@
+package com.fasterxml.jackson.databind.convert;
+
+import java.io.File;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.Calendar;
+import java.util.Currency;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.UUID;
+import java.util.regex.Pattern;
+
+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.MismatchedInputException;
+
+public class CoerceMiscScalarsTest extends BaseMapTest
+{
+ private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
+
+ private final ObjectMapper MAPPER_EMPTY_TO_EMPTY;
+ {
+ MAPPER_EMPTY_TO_EMPTY = newJsonMapper();
+ MAPPER_EMPTY_TO_EMPTY.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsEmpty);
+ }
+
+ private final ObjectMapper MAPPER_EMPTY_TO_TRY_CONVERT;
+ {
+ MAPPER_EMPTY_TO_TRY_CONVERT = newJsonMapper();
+ MAPPER_EMPTY_TO_TRY_CONVERT.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyString, CoercionAction.TryConvert);
+ }
+
+ private final ObjectMapper MAPPER_EMPTY_TO_NULL;
+ {
+ MAPPER_EMPTY_TO_NULL = newJsonMapper();
+ MAPPER_EMPTY_TO_NULL.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyString, CoercionAction.AsNull);
+ }
+
+ private final ObjectMapper MAPPER_EMPTY_TO_FAIL;
+ {
+ MAPPER_EMPTY_TO_FAIL = newJsonMapper();
+ MAPPER_EMPTY_TO_FAIL.coercionConfigDefaults()
+ .setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail);
+ }
+
+ private final String JSON_EMPTY = quote("");
+
+ /*
+ /********************************************************
+ /* Test methods, defaults (legacy)
+ /********************************************************
+ */
+
+ public void testScalarDefaultsFromEmpty() throws Exception
+ {
+ // mostly as null, with some exceptions
+
+ _testScalarEmptyToNull(DEFAULT_MAPPER, File.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, URL.class);
+
+ _testScalarEmptyToEmpty(DEFAULT_MAPPER, URI.class,
+ URI.create(""));
+
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Class.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, JavaType.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Currency.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Pattern.class);
+
+ _testScalarEmptyToEmpty(DEFAULT_MAPPER, Locale.class,
+ Locale.ROOT);
+
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Charset.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, TimeZone.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, InetAddress.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, InetSocketAddress.class);
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, successful coercions from empty String
+ /********************************************************
+ */
+
+ public void testScalarEmptyToNull() throws Exception
+ {
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, File.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, URL.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, URI.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Class.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, JavaType.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Currency.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Pattern.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Locale.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Charset.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, TimeZone.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, InetAddress.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, InetSocketAddress.class);
+ }
+
+ public void testScalarEmptyToEmpty() throws Exception
+ {
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, File.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, URL.class);
+
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_EMPTY, URI.class,
+ URI.create(""));
+
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, Class.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, JavaType.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, Currency.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, Pattern.class);
+
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_EMPTY, Locale.class,
+ Locale.ROOT);
+
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, Charset.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, TimeZone.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, InetAddress.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_EMPTY, InetSocketAddress.class);
+ }
+
+ public void testScalarEmptyToTryConvert() throws Exception
+ {
+ // Should be same as `AsNull` for most but not all
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, File.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, URL.class);
+
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_TRY_CONVERT, URI.class,
+ URI.create(""));
+
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Class.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, JavaType.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Currency.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Pattern.class);
+
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_TRY_CONVERT, Locale.class,
+ Locale.ROOT);
+
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Charset.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, TimeZone.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, InetAddress.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, InetSocketAddress.class);
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, failed coercions from empty String
+ /********************************************************
+ */
+
+ public void testScalarsFailFromEmpty() throws Exception
+ {
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, File.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, URL.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, URI.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Class.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, JavaType.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Currency.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Pattern.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Locale.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Charset.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, TimeZone.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, InetAddress.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, InetSocketAddress.class);
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, (more) special type(s)
+ /********************************************************
+ */
+
+ // UUID is quite compatible, but not exactly due to historical reasons;
+ // also uses custom subtype, so test separately
+
+ public void testUUIDCoercions() throws Exception
+ {
+ // Coerce to `null` both by default, "TryConvert" and explicit
+ _testScalarEmptyToNull(DEFAULT_MAPPER, UUID.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, UUID.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, UUID.class);
+
+ // but allow separate "empty" value is specifically requested
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_EMPTY, UUID.class,
+ new UUID(0L, 0L));
+
+ // allow forcing failure, too
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, UUID.class);
+
+ // and allow failure with specifically configured per-class override, too
+ ObjectMapper failMapper = newJsonMapper();
+ failMapper.coercionConfigFor(UUID.class)
+ .setCoercion(CoercionInputShape.EmptyString, CoercionAction.Fail);
+ _verifyScalarToFail(failMapper, UUID.class);
+ }
+
+ // StringBuilder is its own special type, since it naturally maps
+ // from String values, hence separate testing
+ public void testStringBuilderCoercions() throws Exception
+ {
+ // should result in an "empty" StringBuilder for all valid settings
+ _checkEmptyStringBuilder(DEFAULT_MAPPER.readValue(JSON_EMPTY, StringBuilder.class));
+ _checkEmptyStringBuilder(MAPPER_EMPTY_TO_EMPTY.readValue(JSON_EMPTY, StringBuilder.class));
+ _checkEmptyStringBuilder(MAPPER_EMPTY_TO_TRY_CONVERT.readValue(JSON_EMPTY, StringBuilder.class));
+ _checkEmptyStringBuilder(MAPPER_EMPTY_TO_NULL.readValue(JSON_EMPTY, StringBuilder.class));
+ // and even alleged failure should not result in that since it's not coercion
+ _checkEmptyStringBuilder(MAPPER_EMPTY_TO_FAIL.readValue(JSON_EMPTY, StringBuilder.class));
+ }
+
+ private void _checkEmptyStringBuilder(StringBuilder sb) {
+ assertNotNull(sb);
+ assertEquals(0, sb.length());
+ }
+
+ // Date, Calendar also included here for convenience
+
+ public void testLegacyDateTimeCoercions() throws Exception
+ {
+ // Coerce to `null` both by default, "TryConvert" and explicit
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Calendar.class);
+ _testScalarEmptyToNull(DEFAULT_MAPPER, Date.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Calendar.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_NULL, Date.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Calendar.class);
+ _testScalarEmptyToNull(MAPPER_EMPTY_TO_TRY_CONVERT, Date.class);
+
+ // but allow separate "empty" value is specifically requested
+ Calendar emptyCal = new GregorianCalendar();
+ emptyCal.setTimeInMillis(0L);
+// _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_EMPTY, Calendar.class, emptyCal);
+ _testScalarEmptyToEmpty(MAPPER_EMPTY_TO_EMPTY, Date.class, new Date(0L));
+
+ // allow forcing failure, too
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Calendar.class);
+ _verifyScalarToFail(MAPPER_EMPTY_TO_FAIL, Date.class);
+ }
+
+ /*
+ /********************************************************
+ /* Second-level test helper methods
+ /********************************************************
+ */
+
+ private void _testScalarEmptyToNull(ObjectMapper mapper, Class<?> target) throws Exception
+ {
+ assertNull(mapper.readerFor(target).readValue(JSON_EMPTY));
+ }
+
+ private void _testScalarEmptyToEmpty(ObjectMapper mapper,
+ Class<?> target, Object emptyValue) throws Exception
+ {
+ Object result = mapper.readerFor(target).readValue(JSON_EMPTY);
+ if (result == null) {
+ fail("Expected empty, non-null value for "+target.getName()+", got null");
+ }
+ assertEquals(emptyValue, result);
+ }
+
+ private void _verifyScalarToFail(ObjectMapper mapper, Class<?> target) throws Exception
+ {
+ try {
+ /*Object result =*/ mapper.readerFor(target)
+ .readValue(JSON_EMPTY);
+ fail("Should not pass");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "Cannot coerce empty String ");
+ verifyException(e, " to `"+target.getName());
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoercePojosTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoercePojosTest.java
new file mode 100644
index 000000000..79d63c4d8
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoercePojosTest.java
@@ -0,0 +1,188 @@
+package com.fasterxml.jackson.databind.convert;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.cfg.CoercionAction;
+import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.type.LogicalType;
+
+public class CoercePojosTest extends BaseMapTest
+{
+ static class Bean {
+ public String a;
+ }
+
+ private final ObjectMapper MAPPER = newJsonMapper();
+
+ private final String JSON_EMPTY = quote("");
+ private final String JSON_BLANK = quote(" ");
+
+ /*
+ /********************************************************
+ /* Test methods, from empty String
+ /********************************************************
+ */
+
+ public void testPOJOFromEmptyStringLegacy() throws Exception
+ {
+ // first, verify default settings which do not accept empty String:
+ assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT));
+
+ // should be ok to enable dynamically
+ _verifyFromEmptyPass(MAPPER.reader()
+ .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT),
+ JSON_EMPTY);
+
+ }
+
+ public void testPOJOFromEmptyGlobalConfig() throws Exception
+ {
+ _testPOJOFromEmptyGlobalConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null);
+ }
+
+ public void testPOJOFromEmptyLogicalTypeConfig() throws Exception
+ {
+ _testPOJOFromEmptyLogicalTypeConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null);
+ }
+
+ public void testPOJOFromEmptyPhysicalTypeConfig() throws Exception
+ {
+ _testPOJOFromEmptyPhysicalTypeConfig(CoercionInputShape.EmptyString, JSON_EMPTY, null);
+ }
+
+ /*
+ /********************************************************
+ /* Test methods, from blank String
+ /********************************************************
+ */
+
+ public void testPOJOFromBlankGlobalConfig() throws Exception
+ {
+ _testPOJOFromEmptyGlobalConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE);
+ }
+
+ public void testPOJOFromBlankLogicalTypeConfig() throws Exception
+ {
+ _testPOJOFromEmptyLogicalTypeConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE);
+ }
+
+ public void testPOJOFromBlankPhysicalTypeConfig() throws Exception
+ {
+ _testPOJOFromEmptyPhysicalTypeConfig(CoercionInputShape.EmptyString, JSON_BLANK, Boolean.TRUE);
+ }
+
+ /*
+ /********************************************************
+ /* Second-level helper methods
+ /********************************************************
+ */
+
+ private void _testPOJOFromEmptyGlobalConfig(final CoercionInputShape shape, final String json,
+ Boolean allowEmpty)
+ throws Exception
+ {
+ ObjectMapper mapper;
+
+ // First, coerce to null
+ mapper = newJsonMapper();
+ mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsNull)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ assertNull(_verifyFromEmptyPass(mapper, json));
+
+ // Then coerce as empty
+ mapper = newJsonMapper();
+ mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsEmpty)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ Bean b = _verifyFromEmptyPass(mapper, json);
+ assertNotNull(b);
+
+ // and finally, "try convert", which aliases to 'null'
+ mapper = newJsonMapper();
+ mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.TryConvert)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ assertNull(_verifyFromEmptyPass(mapper, json));
+ }
+
+ private void _testPOJOFromEmptyLogicalTypeConfig(final CoercionInputShape shape, final String json,
+ Boolean allowEmpty)
+ throws Exception
+ {
+ ObjectMapper mapper;
+
+ // First, coerce to null
+ mapper = newJsonMapper();
+ mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsNull)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ assertNull(_verifyFromEmptyPass(mapper, json));
+
+ // Then coerce as empty
+ mapper = newJsonMapper();
+ mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsEmpty)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ Bean b = _verifyFromEmptyPass(mapper, json);
+ assertNotNull(b);
+
+ // But also make fail again with 2-level settings
+ mapper = newJsonMapper();
+ mapper.coercionConfigDefaults().setCoercion(shape, CoercionAction.AsNull)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape,
+ CoercionAction.Fail);
+ _verifyFromEmptyFail(mapper, json);
+ }
+
+ private void _testPOJOFromEmptyPhysicalTypeConfig(final CoercionInputShape shape, final String json,
+ Boolean allowEmpty)
+ throws Exception
+ {
+ ObjectMapper mapper;
+
+ // First, coerce to null
+ mapper = newJsonMapper();
+ mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.AsNull)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ assertNull(_verifyFromEmptyPass(mapper, json));
+
+ // Then coerce as empty
+ mapper = newJsonMapper();
+ mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.AsEmpty)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ Bean b = _verifyFromEmptyPass(mapper, json);
+ assertNotNull(b);
+
+ // But also make fail again with 2-level settings, with physical having precedence
+ mapper = newJsonMapper();
+ mapper.coercionConfigFor(LogicalType.POJO).setCoercion(shape, CoercionAction.AsEmpty)
+ .setAcceptBlankAsEmpty(allowEmpty);
+ mapper.coercionConfigFor(Bean.class).setCoercion(shape, CoercionAction.Fail);
+ _verifyFromEmptyFail(mapper, json);
+ }
+
+ private Bean _verifyFromEmptyPass(ObjectMapper m, String json) throws Exception {
+ return _verifyFromEmptyPass(m.reader(), json);
+ }
+
+ private Bean _verifyFromEmptyPass(ObjectReader r, String json) throws Exception
+ {
+ return r.forType(Bean.class)
+ .readValue(json);
+ }
+
+ private void _verifyFromEmptyFail(ObjectMapper m, String json) throws Exception
+ {
+ try {
+ m.readValue(json, Bean.class);
+ fail("Should not accept Empty/Blank String for POJO with passed settings");
+ } catch (MismatchedInputException e) {
+ _verifyFailMessage(e);
+ }
+ }
+
+ private void _verifyFailMessage(JsonProcessingException e)
+ {
+ verifyException(e, "Cannot deserialize value of type ");
+ verifyException(e, " from empty String ", " from blank String ");
+ assertValidLocation(e.getLocation());
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/CoerceToBooleanTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceToBooleanTest.java
new file mode 100644
index 000000000..f78c14db1
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/CoerceToBooleanTest.java
@@ -0,0 +1,273 @@
+package com.fasterxml.jackson.databind.convert;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectReader;
+import com.fasterxml.jackson.databind.cfg.CoercionAction;
+import com.fasterxml.jackson.databind.cfg.CoercionInputShape;
+import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.type.LogicalType;
+
+public class CoerceToBooleanTest extends BaseMapTest
+{
+ static class BooleanPOJO {
+ public boolean value;
+ }
+
+ private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
+
+ private final ObjectMapper LEGACY_NONCOERCING_MAPPER = jsonMapperBuilder()
+ .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+ .build();
+
+ private final ObjectMapper MAPPER_TO_EMPTY; {
+ MAPPER_TO_EMPTY = newJsonMapper();
+ MAPPER_TO_EMPTY.coercionConfigFor(LogicalType.Boolean)
+ .setCoercion(CoercionInputShape.Integer, CoercionAction.AsEmpty);
+ }
+
+ private final ObjectMapper MAPPER_TRY_CONVERT; {
+ MAPPER_TRY_CONVERT = newJsonMapper();
+ MAPPER_TRY_CONVERT.coercionConfigFor(LogicalType.Boolean)
+ .setCoercion(CoercionInputShape.Integer, CoercionAction.TryConvert);
+ }
+
+ private final ObjectMapper MAPPER_TO_NULL; {
+ MAPPER_TO_NULL = newJsonMapper();
+ MAPPER_TO_NULL.coercionConfigFor(LogicalType.Boolean)
+ .setCoercion(CoercionInputShape.Integer, CoercionAction.AsNull);
+ }
+
+ private final ObjectMapper MAPPER_TO_FAIL; {
+ MAPPER_TO_FAIL = newJsonMapper();
+ MAPPER_TO_FAIL.coercionConfigFor(LogicalType.Boolean)
+ .setCoercion(CoercionInputShape.Integer, CoercionAction.Fail);
+ }
+
+ private final static String DOC_WITH_0 = aposToQuotes("{'value':0}");
+ private final static String DOC_WITH_1 = aposToQuotes("{'value':1}");
+
+ /*
+ /**********************************************************
+ /* Unit tests: default, legacy configuration
+ /**********************************************************
+ */
+
+ public void testToBooleanCoercionSuccessPojo() throws Exception
+ {
+ BooleanPOJO p;
+ final ObjectReader r = DEFAULT_MAPPER.readerFor(BooleanPOJO.class);
+
+ p = r.readValue(DOC_WITH_0);
+ assertEquals(false, p.value);
+ p = r.readValue(utf8Bytes(DOC_WITH_0));
+ assertEquals(false, p.value);
+
+ p = r.readValue(DOC_WITH_1);
+ assertEquals(true, p.value);
+ p = r.readValue(utf8Bytes(DOC_WITH_1));
+ assertEquals(true, p.value);
+ }
+
+ public void testToBooleanCoercionSuccessRoot() throws Exception
+ {
+ final ObjectReader br = DEFAULT_MAPPER.readerFor(Boolean.class);
+
+ assertEquals(Boolean.FALSE, br.readValue(" 0"));
+ assertEquals(Boolean.FALSE, br.readValue(utf8Bytes(" 0")));
+ assertEquals(Boolean.TRUE, br.readValue(" -1"));
+ assertEquals(Boolean.TRUE, br.readValue(utf8Bytes(" -1")));
+
+ final ObjectReader atomicR = DEFAULT_MAPPER.readerFor(AtomicBoolean.class);
+
+ AtomicBoolean ab;
+
+ ab = atomicR.readValue(" 0");
+ ab = atomicR.readValue(utf8Bytes(" 0"));
+ assertEquals(false, ab.get());
+
+ ab = atomicR.readValue(" 111");
+ assertEquals(true, ab.get());
+ ab = atomicR.readValue(utf8Bytes(" 111"));
+ assertEquals(true, ab.get());
+ }
+
+ public void testToBooleanCoercionFailBytes() throws Exception
+ {
+ _verifyBooleanCoerceFail(aposToQuotes("{'value':1}"), true, JsonToken.VALUE_NUMBER_INT, "1", BooleanPOJO.class);
+
+ _verifyBooleanCoerceFail("1", true, JsonToken.VALUE_NUMBER_INT, "1", Boolean.TYPE);
+ _verifyBooleanCoerceFail("1", true, JsonToken.VALUE_NUMBER_INT, "1", Boolean.class);
+ }
+
+ public void testToBooleanCoercionFailChars() throws Exception
+ {
+ _verifyBooleanCoerceFail(aposToQuotes("{'value':1}"), false, JsonToken.VALUE_NUMBER_INT, "1", BooleanPOJO.class);
+
+ _verifyBooleanCoerceFail("1", false, JsonToken.VALUE_NUMBER_INT, "1", Boolean.TYPE);
+ _verifyBooleanCoerceFail("1", false, JsonToken.VALUE_NUMBER_INT, "1", Boolean.class);
+ }
+
+ /*
+ /**********************************************************
+ /* Unit tests: new CoercionConfig, as-null, as-empty, try-coerce
+ /**********************************************************
+ */
+
+ public void testIntToNullCoercion() throws Exception
+ {
+ assertNull(MAPPER_TO_NULL.readValue("0", Boolean.class));
+ assertNull(MAPPER_TO_NULL.readValue("1", Boolean.class));
+
+ // but due to coercion to `boolean`, can not return null here -- however,
+ // goes "1 -> false (no null for primitive) -> Boolean.FALSE
+ assertEquals(Boolean.FALSE, MAPPER_TO_NULL.readValue("0", Boolean.TYPE));
+ assertEquals(Boolean.FALSE, MAPPER_TO_NULL.readValue("1", Boolean.TYPE));
+
+ // As to AtomicBoolean: that type itself IS nullable since it's of LogicalType.Boolean so
+ assertNull(MAPPER_TO_NULL.readValue("0", AtomicBoolean.class));
+ assertNull(MAPPER_TO_NULL.readValue("1", AtomicBoolean.class));
+
+ BooleanPOJO p;
+ p = MAPPER_TO_NULL.readValue(DOC_WITH_0, BooleanPOJO.class);
+ assertFalse(p.value);
+ p = MAPPER_TO_NULL.readValue(DOC_WITH_1, BooleanPOJO.class);
+ assertFalse(p.value);
+ }
+
+ public void testIntToEmptyCoercion() throws Exception
+ {
+ // "empty" value for Boolean/boolean is False/false
+
+ assertEquals(Boolean.FALSE, MAPPER_TO_EMPTY.readValue("0", Boolean.class));
+ assertEquals(Boolean.FALSE, MAPPER_TO_EMPTY.readValue("1", Boolean.class));
+
+ assertEquals(Boolean.FALSE, MAPPER_TO_EMPTY.readValue("0", Boolean.TYPE));
+ assertEquals(Boolean.FALSE, MAPPER_TO_EMPTY.readValue("1", Boolean.TYPE));
+
+ AtomicBoolean ab;
+ ab = MAPPER_TO_EMPTY.readValue("0", AtomicBoolean.class);
+ assertFalse(ab.get());
+ ab = MAPPER_TO_EMPTY.readValue("1", AtomicBoolean.class);
+ assertFalse(ab.get());
+
+ BooleanPOJO p;
+ p = MAPPER_TO_EMPTY.readValue(DOC_WITH_0, BooleanPOJO.class);
+ assertFalse(p.value);
+ p = MAPPER_TO_EMPTY.readValue(DOC_WITH_1, BooleanPOJO.class);
+ assertFalse(p.value);
+ }
+
+ public void testIntToTryCoercion() throws Exception
+ {
+ // And "TryCoerce" should do what would be typically expected
+
+ assertEquals(Boolean.FALSE, MAPPER_TRY_CONVERT.readValue("0", Boolean.class));
+ assertEquals(Boolean.TRUE, MAPPER_TRY_CONVERT.readValue("1", Boolean.class));
+
+ assertEquals(Boolean.FALSE, MAPPER_TRY_CONVERT.readValue("0", Boolean.TYPE));
+ assertEquals(Boolean.TRUE, MAPPER_TRY_CONVERT.readValue("1", Boolean.TYPE));
+
+ AtomicBoolean ab;
+ ab = MAPPER_TRY_CONVERT.readValue("0", AtomicBoolean.class);
+ assertFalse(ab.get());
+ ab = MAPPER_TRY_CONVERT.readValue("1", AtomicBoolean.class);
+ assertTrue(ab.get());
+
+ BooleanPOJO p;
+ p = MAPPER_TRY_CONVERT.readValue(DOC_WITH_0, BooleanPOJO.class);
+ assertFalse(p.value);
+ p = MAPPER_TRY_CONVERT.readValue(DOC_WITH_1, BooleanPOJO.class);
+ assertTrue(p.value);
+ }
+
+ /*
+ /**********************************************************
+ /* Unit tests: new CoercionConfig, failing
+ /**********************************************************
+ */
+
+ public void testFailFromInteger() throws Exception
+ {
+ _verifyFailFromInteger(MAPPER_TO_FAIL, BooleanPOJO.class, DOC_WITH_0, Boolean.TYPE);
+ _verifyFailFromInteger(MAPPER_TO_FAIL, BooleanPOJO.class, DOC_WITH_1, Boolean.TYPE);
+
+ _verifyFailFromInteger(MAPPER_TO_FAIL, Boolean.class, "0");
+ _verifyFailFromInteger(MAPPER_TO_FAIL, Boolean.class, "42");
+
+ _verifyFailFromInteger(MAPPER_TO_FAIL, Boolean.TYPE, "0");
+ _verifyFailFromInteger(MAPPER_TO_FAIL, Boolean.TYPE, "999");
+
+ _verifyFailFromInteger(MAPPER_TO_FAIL, AtomicBoolean.class, "0");
+ _verifyFailFromInteger(MAPPER_TO_FAIL, AtomicBoolean.class, "-123");
+ }
+
+ /*
+ /**********************************************************
+ /* Helper methods
+ /**********************************************************
+ */
+
+ private void _verifyBooleanCoerceFail(String doc, boolean useBytes,
+ JsonToken tokenType, String tokenValue, Class<?> targetType) throws IOException
+ {
+ // Test failure for root value: for both byte- and char-backed sources.
+
+ // [databind#2635]: important, need to use `readValue()` that takes content and NOT
+ // JsonParser, as this forces closing of underlying parser and exposes more issues.
+
+ final ObjectReader r = LEGACY_NONCOERCING_MAPPER.readerFor(targetType);
+ try {
+ if (useBytes) {
+ r.readValue(utf8Bytes(doc));
+ } else {
+ r.readValue(doc);
+ }
+ fail("Should not have allowed coercion");
+ } catch (MismatchedInputException e) {
+ _verifyBooleanCoerceFailReason(e, tokenType, tokenValue);
+ }
+ }
+
+ @SuppressWarnings("resource")
+ private void _verifyBooleanCoerceFailReason(MismatchedInputException e,
+ JsonToken tokenType, String tokenValue) throws IOException
+ {
+ verifyException(e, "Cannot coerce ");
+ verifyException(e, " to `");
+
+ JsonParser p = (JsonParser) e.getProcessor();
+
+ assertToken(tokenType, p.currentToken());
+
+ final String text = p.getText();
+ if (!tokenValue.equals(text)) {
+ String textDesc = (text == null) ? "NULL" : quote(text);
+ fail("Token text ("+textDesc+") via parser of type "+p.getClass().getName()
+ +" not as expected ("+quote(tokenValue)+")");
+ }
+ }
+
+ private void _verifyFailFromInteger(ObjectMapper m, Class<?> targetType, String doc) throws Exception {
+ _verifyFailFromInteger(m, targetType, doc, targetType);
+ }
+
+ private void _verifyFailFromInteger(ObjectMapper m, Class<?> targetType, String doc,
+ Class<?> valueType) throws Exception
+ {
+ try {
+ m.readerFor(targetType).readValue(doc);
+ fail("Should not accept Integer for "+targetType.getName()+" by default");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "Cannot coerce Integer value");
+ verifyException(e, "to `"+valueType.getName()+"`");
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java b/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java
deleted file mode 100644
index 03f79cfe0..000000000
--- a/src/test/java/com/fasterxml/jackson/databind/convert/NumericConversionTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.fasterxml.jackson.databind.convert;
-
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.exc.MismatchedInputException;
-
-public class NumericConversionTest extends BaseMapTest
-{
- private final ObjectMapper MAPPER = sharedMapper();
- private final ObjectReader R = MAPPER.reader().without(DeserializationFeature.ACCEPT_FLOAT_AS_INT);
-
- public void testDoubleToInt() throws Exception
- {
- // by default, should be ok
- Integer I = MAPPER.readValue(" 1.25 ", Integer.class);
- assertEquals(1, I.intValue());
- IntWrapper w = MAPPER.readValue("{\"i\":-2.25 }", IntWrapper.class);
- assertEquals(-2, w.i);
- int[] arr = MAPPER.readValue("[ 1.25 ]", int[].class);
- assertEquals(1, arr[0]);
-
- try {
- R.forType(Integer.class).readValue("1.5");
- fail("Should not pass");
- } catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- try {
- R.forType(Integer.TYPE).readValue("1.5");
- fail("Should not pass");
- } catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- try {
- R.forType(IntWrapper.class).readValue("{\"i\":-2.25 }");
- fail("Should not pass");
- } catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- try {
- R.forType(int[].class).readValue("[ 2.5 ]");
- fail("Should not pass");
- } catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- }
-
- public void testDoubleToLong() throws Exception
- {
- // by default, should be ok
- Long L = MAPPER.readValue(" 3.33 ", Long.class);
- assertEquals(3L, L.longValue());
- LongWrapper w = MAPPER.readValue("{\"l\":-2.25 }", LongWrapper.class);
- assertEquals(-2L, w.l);
- long[] arr = MAPPER.readValue("[ 1.25 ]", long[].class);
- assertEquals(1, arr[0]);
-
- try {
- R.forType(Long.class).readValue("1.5");
- fail("Should not pass");
- } catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
-
- try {
- R.forType(Long.TYPE).readValue("1.5");
- fail("Should not pass");
- } catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
-
- try {
- R.forType(LongWrapper.class).readValue("{\"l\": 7.7 }");
- fail("Should not pass");
- } catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- try {
- R.forType(long[].class).readValue("[ 2.5 ]");
- fail("Should not pass");
- } catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce a floating-point");
- }
- }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
index fbc4751bb..33117d4aa 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestArrayConversions.java
@@ -12,7 +12,7 @@ public class TestArrayConversions
extends com.fasterxml.jackson.databind.BaseMapTest
{
final static String OVERFLOW_MSG_BYTE = "out of range of Java byte";
- final static String OVERFLOW_MSG = "overflow";
+ final static String OVERFLOW_MSG_SHORT = "out of range of Java short";
final static String OVERFLOW_MSG_INT = "out of range of int";
final static String OVERFLOW_MSG_LONG = "out of range of long";
@@ -103,7 +103,7 @@ public class TestArrayConversions
try {
MAPPER.convertValue(new int[] { -99999 }, short[].class);
} catch (IllegalArgumentException e) {
- verifyException(e, OVERFLOW_MSG);
+ verifyException(e, OVERFLOW_MSG_SHORT);
}
// Int overflow
try {
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestMapConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestMapConversions.java
index bfed9dffe..aabe0eaa3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestMapConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestMapConversions.java
@@ -70,11 +70,11 @@ public class TestMapConversions
public void testMapToBean()
{
EnumMap<AB,String> map = new EnumMap<AB,String>(AB.class);
- map.put(AB.A, " 17");
- map.put(AB.B, " -1");
+ map.put(AB.A, "17");
+ map.put(AB.B, "-1");
Bean bean = MAPPER.convertValue(map, Bean.class);
assertEquals(Integer.valueOf(17), bean.A);
- assertEquals(" -1", bean.B);
+ assertEquals("-1", bean.B);
}
public void testBeanToMap()
diff --git a/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java b/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
index 93a9d67b1..5f874ce93 100644
--- a/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
+++ b/src/test/java/com/fasterxml/jackson/databind/convert/TestStringConversions.java
@@ -35,7 +35,7 @@ public class TestStringConversions
public void testSimple()
{
assertEquals(Boolean.TRUE, MAPPER.convertValue("true", Boolean.class));
- assertEquals(Integer.valueOf(-3), MAPPER.convertValue(" -3 ", Integer.class));
+ assertEquals(Integer.valueOf(-3), MAPPER.convertValue("-3", Integer.class));
assertEquals(Long.valueOf(77), MAPPER.convertValue("77", Long.class));
int[] ints = { 1, 2, 3 };
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java
deleted file mode 100644
index 7741337eb..000000000
--- a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeser1805Test.java
+++ /dev/null
@@ -1,78 +0,0 @@
-package com.fasterxml.jackson.databind.deser;
-
-import java.util.*;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.*;
-
-public class ReadOnlyDeser1805Test extends BaseMapTest
-{
- static class Foo {
- @JsonProperty(access = JsonProperty.Access.READ_ONLY)
- private List<Long> list = new ArrayList<>();
-
- List<Long> getList() {
- return list;
- }
-
- public Foo setList(List<Long> list) {
- this.list = list;
- return this;
- }
- }
-
- // [databind#1805]
- static class UserWithReadOnly {
- public String name;
-
- @JsonProperty(access = JsonProperty.Access.READ_ONLY)
- public List<String> getRoles() {
- return Arrays.asList("admin", "monitor");
- }
- }
-
- // [databind#1805]
- @JsonIgnoreProperties(value={ "roles" }, allowGetters=true)
- static class UserAllowGetters {
- public String name;
-
- public List<String> getRoles() {
- return Arrays.asList("admin", "monitor");
- }
- }
-
- /*
- /**********************************************************
- /* Test methods
- /**********************************************************
- */
-
- private final ObjectMapper MAPPER = newJsonMapper();
-
- public void testReadOnly1382() throws Exception
- {
- String payload = "{\"list\":[1,2,3,4]}";
- Foo foo = MAPPER.readValue(payload, Foo.class);
- assertTrue("List should be empty", foo.getList().isEmpty());
- }
-
- // [databind#1805]
- public void testViaReadOnly() throws Exception {
- UserWithReadOnly user = new UserWithReadOnly();
- user.name = "foo";
- String json = MAPPER.writeValueAsString(user);
- UserWithReadOnly result = MAPPER.readValue(json, UserWithReadOnly.class);
- assertNotNull(result);
- }
-
- // [databind#1805]
- public void testUsingAllowGetters() throws Exception {
- UserAllowGetters user = new UserAllowGetters();
- user.name = "foo";
- String json = MAPPER.writeValueAsString(user);
- assertTrue(json.contains("roles"));
- UserAllowGetters result = MAPPER.readValue(json, UserAllowGetters.class);
- assertNotNull(result);
- }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeserFailOnUnknown2719Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeserFailOnUnknown2719Test.java
new file mode 100644
index 000000000..7e1f6ea51
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyDeserFailOnUnknown2719Test.java
@@ -0,0 +1,52 @@
+package com.fasterxml.jackson.databind.deser;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.databind.*;
+
+public class ReadOnlyDeserFailOnUnknown2719Test extends BaseMapTest
+{
+ // [databind#2719]
+ static class UserWithReadOnly {
+ @JsonProperty(value = "username", access = JsonProperty.Access.READ_ONLY)
+ public String name;
+ @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+ public String password;
+ public String login;
+ }
+
+ /*
+ /**********************************************************
+ /* Test methods
+ /**********************************************************
+ */
+
+ private final ObjectMapper MAPPER = newJsonMapper();
+
+ public void testFailOnIgnore() throws Exception
+ {
+ ObjectReader r = MAPPER.readerFor(UserWithReadOnly.class);
+
+ // First, fine to get 'login'
+ UserWithReadOnly result = r.readValue(aposToQuotes("{'login':'foo'}"));
+ assertEquals("foo", result.login);
+
+ // but not 'password'
+ r = r.with(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
+ try {
+ r.readValue(aposToQuotes("{'login':'foo', 'password':'bar'}"));
+ fail("Should fail");
+ } catch (JsonMappingException e) {
+ verifyException(e, "Ignored field");
+ }
+
+ // or 'username'
+ r = r.with(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
+ try {
+ r.readValue(aposToQuotes("{'login':'foo', 'username':'bar'}"));
+ fail("Should fail");
+ } catch (JsonMappingException e) {
+ verifyException(e, "Ignored field");
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/PropertyAccessReadOnly2118Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2118Test.java
index fa7860885..0fb1e5cb9 100644
--- a/src/test/java/com/fasterxml/jackson/failing/PropertyAccessReadOnly2118Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2118Test.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.deser;
import java.util.*;
@@ -6,12 +6,11 @@ import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.*;
-public class PropertyAccessReadOnly2118Test extends BaseMapTest
+public class ReadOnlyListDeser2118Test extends BaseMapTest
{
// [databind#2118]
static class SecurityGroup {
-
- private List<SecurityGroupRule> securityGroupRules;
+ List<SecurityGroupRule> securityGroupRules;
public SecurityGroup() {
this.securityGroupRules = new ArrayList<>();
@@ -40,15 +39,21 @@ public class PropertyAccessReadOnly2118Test extends BaseMapTest
public void setId(String id) {
this.id = id;
}
+
+ @Override
+ public String toString() {
+ return "{SecurityGroupRule '"+id+"'}";
+ }
}
+ private final ObjectMapper mapper = newJsonMapper();
+
// [databind#2118]
public void testAccessReadOnly() throws Exception {
- String data ="{\"security_group_rules\": [{\"id\": \"id1\"}, {\"id\": \"id2\"}, {\"id\": \"id3\"}, {\"id\": \"id4\"}]}";
- ObjectMapper mapper = new ObjectMapper();
-// This would work around the issue:
+ String data ="{\"security_group_rules\": [{\"id\": \"id1\"}]}";
+// This would work around the issue:
// mapper.disable(MapperFeature.USE_GETTERS_AS_SETTERS);
SecurityGroup sg = mapper.readValue(data, SecurityGroup.class);
- System.out.println(mapper.writeValueAsString(sg));
+ assertEquals(Collections.emptyList(), sg.securityGroupRules);
}
}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ReadOnlyList2283Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2283Test.java
index 533265fc4..66e0fc527 100644
--- a/src/test/java/com/fasterxml/jackson/failing/ReadOnlyList2283Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOnlyListDeser2283Test.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.deser;
import java.util.*;
@@ -7,7 +7,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.*;
// [databind#2283]: ignore read-only Lists even if "getter-as-setter" enabled
-public class ReadOnlyList2283Test
+public class ReadOnlyListDeser2283Test
extends BaseMapTest
{
static class RenamedToSameOnGetter {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
index 0afd3ffb9..21f35c356 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/ReadOrWriteOnlyTest.java
@@ -1,8 +1,13 @@
package com.fasterxml.jackson.databind.deser;
import java.beans.ConstructorProperties;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
+
import com.fasterxml.jackson.databind.*;
public class ReadOrWriteOnlyTest extends BaseMapTest
@@ -66,6 +71,59 @@ public class ReadOrWriteOnlyTest extends BaseMapTest
protected Foo1345() { }
}
+ // [databind#1382]
+ static class Foo1382 {
+ @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+ private List<Long> list = new ArrayList<>();
+
+ List<Long> getList() {
+ return list;
+ }
+
+ public Foo1382 setList(List<Long> list) {
+ this.list = list;
+ return this;
+ }
+ }
+
+ // [databind#1805]
+ static class UserWithReadOnly1805 {
+ public String name;
+
+ @JsonProperty(access = JsonProperty.Access.READ_ONLY)
+ public List<String> getRoles() {
+ return Arrays.asList("admin", "monitor");
+ }
+ }
+
+ // [databind#1805]
+ @JsonIgnoreProperties(value={ "roles" }, allowGetters=true)
+ static class UserAllowGetters1805 {
+ public String name;
+
+ public List<String> getRoles() {
+ return Arrays.asList("admin", "monitor");
+ }
+ }
+
+ // [databind#2779]: ignorable property renaming
+ static class Bean2779 {
+ String works;
+
+ @JsonProperty(value = "t", access = JsonProperty.Access.READ_ONLY)
+ public String getDoesntWork() {
+ return "pleaseFixThisBug";
+ }
+
+ public String getWorks() {
+ return works;
+ }
+
+ public void setWorks(String works) {
+ this.works = works;
+ }
+ }
+
/*
/**********************************************************
/* Test methods
@@ -93,6 +151,7 @@ public class ReadOrWriteOnlyTest extends BaseMapTest
assertNotNull(result);
}
+ // [databind#1345]
public void testReadOnly1345() throws Exception
{
Foo1345 result = MAPPER.readValue("{\"name\":\"test\"}", Foo1345.class);
@@ -100,4 +159,42 @@ public class ReadOrWriteOnlyTest extends BaseMapTest
assertEquals("test", result.name);
assertNull(result.id);
}
+
+ // [databind#1382]
+ public void testReadOnly1382() throws Exception
+ {
+ String payload = "{\"list\":[1,2,3,4]}";
+ Foo1382 foo = MAPPER.readValue(payload, Foo1382.class);
+ assertTrue("List should be empty", foo.getList().isEmpty());
+ }
+
+ // [databind#1805]
+ public void testViaReadOnly() throws Exception {
+ UserWithReadOnly1805 user = new UserWithReadOnly1805();
+ user.name = "foo";
+ String json = MAPPER.writeValueAsString(user);
+ UserWithReadOnly1805 result = MAPPER.readValue(json, UserWithReadOnly1805.class);
+ assertNotNull(result);
+ }
+
+ // [databind#1805]
+ public void testUsingAllowGetters() throws Exception {
+ UserAllowGetters1805 user = new UserAllowGetters1805();
+ user.name = "foo";
+ String json = MAPPER.writeValueAsString(user);
+ assertTrue(json.contains("roles"));
+ UserAllowGetters1805 result = MAPPER.readValue(json, UserAllowGetters1805.class);
+ assertNotNull(result);
+ }
+
+ // [databind#2779]: ignorable property renaming
+ public void testIssue2779() throws Exception
+ {
+ Bean2779 bean = new Bean2779();
+ bean.setWorks("works");
+
+ String json = MAPPER.writeValueAsString(bean);
+ Bean2779 newBean = MAPPER.readValue(json, Bean2779.class);
+ assertNotNull(newBean);
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
index 988ece38d..05850407c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestBeanDeserializer.java
@@ -322,7 +322,7 @@ public class TestBeanDeserializer extends BaseMapTest
/********************************************************
*/
- private final ObjectMapper MAPPER = new ObjectMapper();
+ private final ObjectMapper MAPPER = newJsonMapper();
/**
* Test to verify details of how trying to deserialize into
@@ -370,24 +370,6 @@ public class TestBeanDeserializer extends BaseMapTest
assertEquals(2, Issue476Deserializer.propCount);
}
- public void testPOJOFromEmptyString() throws Exception
- {
- // first, verify default settings which do not accept empty String:
- assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT));
- try {
- MAPPER.readValue(quote(""), Bean.class);
- fail("Should not accept Empty String for POJO");
- } catch (JsonProcessingException e) {
- verifyException(e, "from String value");
- assertValidLocation(e.getLocation());
- }
- // should be ok to enable dynamically
- ObjectReader r = MAPPER.readerFor(Bean.class)
- .with(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
- Bean result = r.readValue(quote(""));
- assertNull(result);
- }
-
// [databind#120]
public void testModifyArrayDeserializer() throws Exception
{
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderErrorHandling.java b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderErrorHandling.java
index f7f67b0c5..b71c1306a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderErrorHandling.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderErrorHandling.java
@@ -54,7 +54,7 @@ public class BuilderErrorHandling extends BaseMapTest
MAPPER.readValue(json, ValueClassXY.class);
fail("Should not pass");
} catch (MismatchedInputException e) {
- verifyException(e, "unrecognized field");
+ verifyException(e, "Unrecognized field");
}
// but pass if ok to ignore
ValueClassXY result = MAPPER.readerFor(ValueClassXY.class)
@@ -63,4 +63,16 @@ public class BuilderErrorHandling extends BaseMapTest
assertEquals(2, result._x);
assertEquals(5, result._y);
}
+
+ public void testWrongShape() throws Exception
+ {
+ try {
+ MAPPER.readValue("123", ValueClassXY.class);
+ fail("Should not pass");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "Cannot construct instance of ");
+ // should report Builder class, not value here, right?
+ verifyException(e, "$SimpleBuilderXY");
+ }
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderFailTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderFailTest.java
index 55f9feb92..743d52db6 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderFailTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderFailTest.java
@@ -70,7 +70,8 @@ public class BuilderFailTest extends BaseMapTest
MAPPER.readValue(json, ValueClassWrongBuildType.class);
fail("Missing expected InvalidDefinitionException exception");
} catch (InvalidDefinitionException e) {
- verifyException(e, "Build method");
+ verifyException(e, "Build method ");
+ verifyException(e, "#build()");
verifyException(e, "has wrong return type");
}
}
diff --git a/src/test/java/com/fasterxml/jackson/failing/BuilderDeserializationTest921.java b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithTypeParametersTest.java
index 79beaee6f..7b8ddf6fa 100644
--- a/src/test/java/com/fasterxml/jackson/failing/BuilderDeserializationTest921.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/builder/BuilderWithTypeParametersTest.java
@@ -1,13 +1,17 @@
-package com.fasterxml.jackson.failing;
+package com.fasterxml.jackson.databind.deser.builder;
-import java.util.List;
-
-import com.fasterxml.jackson.annotation.*;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import java.util.LinkedHashMap;
+import java.util.List;
-public class BuilderDeserializationTest921
+// [databind#921]: support infering type parameters from Builder
+public class BuilderWithTypeParametersTest
extends BaseMapTest
{
public static class MyPOJO {
@@ -33,6 +37,12 @@ public class BuilderDeserializationTest921
return data;
}
+ // 28-Apr-2020, tatu: Note that as per [databind#921] the NAME of
+ // type variable here MUST match that of enclosing class. This has
+ // no semantic meaning to JDK or javac, but internally
+ // `MapperFeature.INFER_BUILDER_TYPE_BINDINGS` relies on this -- but
+ // can not really validate it. So user just has to rely on bit of
+ // black magic to use generic types with builders.
public static class Builder<T> {
private List<T> data;
@@ -77,15 +87,30 @@ public class BuilderDeserializationTest921
}
}
- public void testWithBuilder() throws Exception {
- final ObjectMapper mapper = new ObjectMapper();
+ public void testWithBuilderInferringBindings() throws Exception {
+ final ObjectMapper mapper = jsonMapperBuilder()
+ .enable(MapperFeature.INFER_BUILDER_TYPE_BINDINGS)
+ .build();
+ final String json = aposToQuotes("{ 'data': [ { 'x': 'x', 'y': 'y' } ] }");
+ final MyGenericPOJO<MyPOJO> deserialized =
+ mapper.readValue(json, new TypeReference<MyGenericPOJO<MyPOJO>>() {});
+ assertEquals(1, deserialized.data.size());
+ Object ob = deserialized.data.get(0);
+ assertNotNull(ob);
+ assertEquals(MyPOJO.class, ob.getClass());
+ }
+
+ public void testWithBuilderWithoutInferringBindings() throws Exception {
+ final ObjectMapper mapper = jsonMapperBuilder()
+ .disable(MapperFeature.INFER_BUILDER_TYPE_BINDINGS)
+ .build();
final String json = aposToQuotes("{ 'data': [ { 'x': 'x', 'y': 'y' } ] }");
final MyGenericPOJO<MyPOJO> deserialized =
mapper.readValue(json, new TypeReference<MyGenericPOJO<MyPOJO>>() {});
assertEquals(1, deserialized.data.size());
Object ob = deserialized.data.get(0);
assertNotNull(ob);
- assertEquals(MyPOJO.class, ob.getClass());
+ assertEquals(LinkedHashMap.class, ob.getClass());
}
public void testWithCreator() throws Exception {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java
index c0ae77ca6..e33897e47 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/DelegatingArrayCreatorsTest.java
@@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.BaseMapTest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
public class DelegatingArrayCreatorsTest extends BaseMapTest
{
@@ -74,6 +75,20 @@ public class DelegatingArrayCreatorsTest extends BaseMapTest
private Bag2324<Value2324> bagOfValues;
}
+ static class MultipleArrayDelegators {
+ @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+ MultipleArrayDelegators(List<Integer> a) { }
+
+ @JsonCreator(mode=JsonCreator.Mode.DELEGATING)
+ MultipleArrayDelegators(Set<Integer> a) { }
+ }
+
+ /*
+ /**********************************************************************
+ /* Test methods
+ /**********************************************************************
+ */
+
private final ObjectMapper MAPPER = sharedMapper();
// [databind#1804]
@@ -96,4 +111,15 @@ public class DelegatingArrayCreatorsTest extends BaseMapTest
assertEquals(3, result.getValues().size());
assertEquals(new Value2324("a"), result.getValues().iterator().next());
}
+
+ public void testInvalidTwoArrayDelegating() throws Exception {
+ try {
+ /*MultipleArrayDelegators result =*/ MAPPER.readerFor(MultipleArrayDelegators.class)
+ .readValue("[ ]");
+ fail("Should not pass");
+ } catch (InvalidDefinitionException e) {
+ verifyException(e, "Conflicting array-delegate creators");
+ verifyException(e, "already had explicitly marked");
+ }
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
index 065172064..edde73955 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/creators/TestCreatorsDelegating.java
@@ -26,7 +26,30 @@ public class TestCreatorsDelegating extends BaseMapTest
}
}
- // for [JACKSON-711]; should allow delegate-based one(s) too
+ static class IntegerBean
+ {
+ protected Integer value;
+
+ public IntegerBean(Integer v) { value = v; }
+
+ @JsonCreator
+ protected static IntegerBean create(Integer value) {
+ return new IntegerBean(value);
+ }
+ }
+
+ static class LongBean
+ {
+ protected Long value;
+
+ public LongBean(Long v) { value = v; }
+
+ @JsonCreator
+ protected static LongBean create(Long value) {
+ return new LongBean(value);
+ }
+ }
+
static class CtorBean711
{
protected String name;
@@ -40,7 +63,6 @@ public class TestCreatorsDelegating extends BaseMapTest
}
}
- // for [JACKSON-711]; should allow delegate-based one(s) too
static class FactoryBean711
{
protected String name1;
@@ -116,7 +138,7 @@ public class TestCreatorsDelegating extends BaseMapTest
*/
private final ObjectMapper MAPPER = newJsonMapper();
-
+
public void testBooleanDelegate() throws Exception
{
// should obviously work with booleans...
@@ -127,8 +149,28 @@ public class TestCreatorsDelegating extends BaseMapTest
bb = MAPPER.readValue(quote("true"), BooleanBean.class);
assertEquals(Boolean.TRUE, bb.value);
}
-
- // As per [JACKSON-711]: should also work with delegate model (single non-annotated arg)
+
+ public void testIntegerDelegate() throws Exception
+ {
+ IntegerBean bb = MAPPER.readValue("-13", IntegerBean.class);
+ assertEquals(Integer.valueOf(-13), bb.value);
+
+ // but also with value conversion from String (unless blocked)
+ bb = MAPPER.readValue(quote("127"), IntegerBean.class);
+ assertEquals(Integer.valueOf(127), bb.value);
+ }
+
+ public void testLongDelegate() throws Exception
+ {
+ LongBean bb = MAPPER.readValue("11", LongBean.class);
+ assertEquals(Long.valueOf(11L), bb.value);
+
+ // but also with value conversion from String (unless blocked)
+ bb = MAPPER.readValue(quote("-99"), LongBean.class);
+ assertEquals(Long.valueOf(-99L), bb.value);
+ }
+
+ // should also work with delegate model (single non-annotated arg)
public void testWithCtorAndDelegate() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
index 953ea8678..a9589daf7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/IgnorePropertyOnDeserTest.java
@@ -10,6 +10,33 @@ import com.fasterxml.jackson.databind.ObjectMapper;
public class IgnorePropertyOnDeserTest extends BaseMapTest
{
+ // [databind#426]
+ @JsonIgnoreProperties({ "userId" })
+ static class User {
+ public String firstName;
+ Integer userId;
+
+ public Integer getUserId() {
+ return userId;
+ }
+
+ public void setUserId(CharSequence id) {
+ userId = Integer.valueOf(id.toString());
+ }
+
+ public void setUserId(Integer v) {
+ this.userId = v;
+ }
+
+ public void setUserId(User u) {
+ // bogus
+ }
+
+ public void setUserId(boolean b) {
+ // bogus
+ }
+ }
+
// [databind#1217]
static class IgnoreObject {
public int x = 1;
@@ -62,6 +89,16 @@ public class IgnorePropertyOnDeserTest extends BaseMapTest
private final ObjectMapper MAPPER = newJsonMapper();
+ // [databind#426]
+ public void testIssue426() throws Exception
+ {
+ final String JSON = aposToQuotes("{'userId': 9, 'firstName': 'Mike' }");
+ User result = MAPPER.readerFor(User.class).readValue(JSON);
+ assertNotNull(result);
+ assertEquals("Mike", result.firstName);
+ assertNull(result.userId);
+ }
+
// [databind#1217]
public void testIgnoreOnProperty1217() throws Exception
{
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
index 85beb40b3..815029a0c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/filter/ProblemHandlerTest.java
@@ -362,7 +362,7 @@ public class ProblemHandlerTest extends BaseMapTest
mapper.readValue("true", Integer.class);
fail("Should not pass");
} catch (MismatchedInputException e) {
- verifyException(e, "out of VALUE_TRUE token");
+ verifyException(e, "from Boolean value (token `JsonToken.VALUE_TRUE`)");
}
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestArrayDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/ArrayDeserializationTest.java
index b0fd99694..ac8838bd8 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestArrayDeserialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/ArrayDeserializationTest.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.jdk;
import java.io.*;
import java.util.*;
@@ -16,7 +16,7 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
* This unit test suite tries to verify that the "Native" java type
* mapper can properly re-construct Java array objects from Json arrays.
*/
-public class TestArrayDeserialization
+public class ArrayDeserializationTest
extends BaseMapTest
{
public final static class Bean1
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
index 2feba30b6..40a9cb958 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/DateDeserializationTest.java
@@ -702,7 +702,7 @@ public class DateDeserializationTest
fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
} catch (MismatchedInputException exp) {
verifyException(exp, "Cannot deserialize");
- verifyException(exp, "out of START_ARRAY");
+ verifyException(exp, "from Array value (token `JsonToken.START_ARRAY`)");
}
reader = reader.with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
index e31636741..4b551193a 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberDeserTest.java
@@ -7,7 +7,10 @@ import java.math.BigInteger;
import java.util.List;
import java.util.Map;
+import com.fasterxml.jackson.annotation.*;
+
import com.fasterxml.jackson.core.*;
+
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
@@ -37,6 +40,42 @@ public class JDKNumberDeserTest extends BaseMapTest
public MyBeanValue(BigDecimal d) { this.decimal = d; }
}
+ // [databind#2644]
+ static class NodeRoot2644 {
+ public String type;
+
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
+ @JsonSubTypes(value = {
+ @JsonSubTypes.Type(value = NodeParent2644.class, name = "NodeParent")
+ })
+ public Node2644 node;
+ }
+
+ public static class NodeParent2644 extends Node2644 { }
+
+ public static abstract class Node2644 {
+ @JsonProperty("amount")
+ BigDecimal val;
+
+ public BigDecimal getVal() {
+ return val;
+ }
+
+ public void setVal(BigDecimal val) {
+ this.val = val;
+ }
+ }
+
+ // [databind#2784]
+ static class BigDecimalHolder2784 {
+ public BigDecimal value;
+ }
+
+ static class NestedBigDecimalHolder2784 {
+ @JsonUnwrapped
+ public BigDecimalHolder2784 holder;
+ }
+
/*
/**********************************************************************
/* Helper classes, serializers/deserializers/resolvers
@@ -138,7 +177,7 @@ public class JDKNumberDeserTest extends BaseMapTest
noCoerceMapper.readValue(NULL_JSON, Integer.TYPE);
fail("Should not have passed");
} catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce String \"null\"");
+ verifyException(e, "Cannot coerce String value");
}
}
@@ -299,4 +338,28 @@ public class JDKNumberDeserTest extends BaseMapTest
}
assertEquals(42, node.asInt());
}
+
+ // [databind#2644]
+ public void testBigDecimalSubtypes() throws Exception
+ {
+ ObjectMapper mapper = jsonMapperBuilder()
+ .registerSubtypes(NodeParent2644.class)
+ .build();
+ NodeRoot2644 root = mapper.readValue(
+ "{\"type\": \"NodeParent\",\"node\": {\"amount\": 9999999999999999.99} }",
+ NodeRoot2644.class
+ );
+
+ assertEquals(new BigDecimal("9999999999999999.99"), root.node.getVal());
+ }
+
+ // [databind#2784]
+ public void testBigDecimalUnwrapped() throws Exception
+ {
+ final ObjectMapper mapper = newJsonMapper();
+ // mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
+ final String JSON = "{\"value\": 5.00}";
+ NestedBigDecimalHolder2784 result = mapper.readValue(JSON, NestedBigDecimalHolder2784.class);
+ assertEquals(new BigDecimal("5.00"), result.holder.value);
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java
index b7269cbf7..47d8bb410 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKNumberLeniencyTest.java
@@ -32,7 +32,7 @@ public class JDKNumberLeniencyTest extends BaseMapTest
fail("Should not allow read in strict mode");
} catch (MismatchedInputException e) {
verifyException(e, "Cannot coerce");
- verifyException(e, "for type `java.lang.Boolean`");
+ verifyException(e, "to `java.lang.Boolean` value");
}
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKScalarsTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKScalarsTest.java
index cdf9ec1ac..7e244a0e3 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKScalarsTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKScalarsTest.java
@@ -2,6 +2,8 @@ package com.fasterxml.jackson.databind.deser.jdk;
import java.io.*;
import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
import java.util.List;
import org.junit.Assert;
@@ -12,6 +14,7 @@ import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.JsonMappingException.Reference;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
+import com.fasterxml.jackson.databind.util.ClassUtil;
/**
* Unit tests for verifying handling of simple basic non-structured
@@ -120,6 +123,10 @@ public class JDKScalarsTest
private final ObjectMapper MAPPER = newJsonMapper();
+ private final ObjectMapper MAPPER_NO_COERCION = jsonMapperBuilder()
+ .disable(MapperFeature.ALLOW_COERCION_OF_SCALARS)
+ .build();
+
/*
/**********************************************************
/* Scalar tests for boolean
@@ -226,12 +233,15 @@ public class JDKScalarsTest
public void testCharacterWrapper() throws Exception
{
// First: canonical value is 1-char string
- Character result = MAPPER.readValue("\"a\"", Character.class);
- assertEquals(Character.valueOf('a'), result);
+ assertEquals(Character.valueOf('a'), MAPPER.readValue(quote("a"), Character.class));
// But can also pass in ascii code
- result = MAPPER.readValue(" "+((int) 'X'), Character.class);
+ Character result = MAPPER.readValue(" "+((int) 'X'), Character.class);
assertEquals(Character.valueOf('X'), result);
+
+ // 22-Jun-2020, tatu: one special case turns out to be white space;
+ // need to avoid considering it "blank" value
+ assertEquals(Character.valueOf(' '), MAPPER.readValue(quote(" "), Character.class));
final CharacterWrapperBean wrapper = MAPPER.readValue("{\"v\":null}", CharacterWrapperBean.class);
assertNotNull(wrapper);
@@ -431,30 +441,6 @@ public class JDKScalarsTest
/**********************************************************
*/
- public void testEmptyToNullCoercionForPrimitives() throws Exception {
- _testEmptyToNullCoercion(int.class, Integer.valueOf(0));
- _testEmptyToNullCoercion(long.class, Long.valueOf(0));
- _testEmptyToNullCoercion(double.class, Double.valueOf(0.0));
- _testEmptyToNullCoercion(float.class, Float.valueOf(0.0f));
- }
-
- private void _testEmptyToNullCoercion(Class<?> primType, Object emptyValue) throws Exception
- {
- final String EMPTY = "\"\"";
-
- // as per [databind#1095] should only allow coercion from empty String,
- // if `null` is acceptable
- ObjectReader intR = MAPPER.readerFor(primType);
- assertEquals(emptyValue, intR.readValue(EMPTY));
- try {
- intR.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES)
- .readValue("\"\"");
- fail("Should not have passed");
- } catch (MismatchedInputException e) {
- verifyException(e, "Cannot coerce empty String");
- }
- }
-
public void testBase64Variants() throws Exception
{
final byte[] INPUT = "abcdefghijklmnopqrstuvwxyz1234567890abcdefghijklmnopqrstuvwxyz1234567890X".getBytes("UTF-8");
@@ -515,13 +501,15 @@ public class JDKScalarsTest
*/
// by default, should return nulls, n'est pas?
- public void testEmptyStringForWrappers() throws IOException
+ public void testEmptyStringForBooleanWrapper() throws IOException
{
- WrappersBean bean;
-
- bean = MAPPER.readValue("{\"booleanValue\":\"\"}", WrappersBean.class);
+ WrappersBean bean = MAPPER.readValue("{\"booleanValue\":\"\"}", WrappersBean.class);
assertNull(bean.booleanValue);
- bean = MAPPER.readValue("{\"byteValue\":\"\"}", WrappersBean.class);
+ }
+
+ public void testEmptyStringForIntegerWrappers() throws IOException
+ {
+ WrappersBean bean = MAPPER.readValue("{\"byteValue\":\"\"}", WrappersBean.class);
assertNull(bean.byteValue);
// char/Character is different... not sure if this should work or not:
@@ -534,18 +522,25 @@ public class JDKScalarsTest
assertNull(bean.intValue);
bean = MAPPER.readValue("{\"longValue\":\"\"}", WrappersBean.class);
assertNull(bean.longValue);
- bean = MAPPER.readValue("{\"floatValue\":\"\"}", WrappersBean.class);
+ }
+
+ public void testEmptyStringForFloatWrappers() throws IOException
+ {
+ WrappersBean bean = MAPPER.readValue("{\"floatValue\":\"\"}", WrappersBean.class);
assertNull(bean.floatValue);
bean = MAPPER.readValue("{\"doubleValue\":\"\"}", WrappersBean.class);
assertNull(bean.doubleValue);
}
- public void testEmptyStringForPrimitives() throws IOException
+ public void testEmptyStringForBooleanPrimitive() throws IOException
{
- PrimitivesBean bean;
- bean = MAPPER.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class);
+ PrimitivesBean bean = MAPPER.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class);
assertFalse(bean.booleanValue);
- bean = MAPPER.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class);
+ }
+
+ public void testEmptyStringForIntegerPrimitives() throws IOException
+ {
+ PrimitivesBean bean = MAPPER.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class);
assertEquals((byte) 0, bean.byteValue);
bean = MAPPER.readValue("{\"charValue\":\"\"}", PrimitivesBean.class);
assertEquals((char) 0, bean.charValue);
@@ -555,38 +550,30 @@ public class JDKScalarsTest
assertEquals(0, bean.intValue);
bean = MAPPER.readValue("{\"longValue\":\"\"}", PrimitivesBean.class);
assertEquals(0L, bean.longValue);
- bean = MAPPER.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class);
+ }
+
+ public void testEmptyStringForFloatPrimitives() throws IOException
+ {
+ PrimitivesBean bean = MAPPER.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class);
assertEquals(0.0f, bean.floatValue);
bean = MAPPER.readValue("{\"doubleValue\":\"\"}", PrimitivesBean.class);
assertEquals(0.0, bean.doubleValue);
}
- private void _verifyEmptyStringFailForPrimitives(String propName) throws IOException
+ // for [databind#403]
+ public void testEmptyStringFailForBooleanPrimitive() throws IOException
{
final ObjectReader reader = MAPPER
.readerFor(PrimitivesBean.class)
.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
try {
- reader.readValue(aposToQuotes("{'"+propName+"':''}"));
+ reader.readValue(aposToQuotes("{'booleanValue':''}"));
fail("Expected failure for boolean + empty String");
} catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce empty String (\"\")");
- verifyException(e, "to Null value");
+ verifyException(e, "Cannot coerce `null` to `boolean`");
+ verifyException(e, "FAIL_ON_NULL_FOR_PRIMITIVES");
}
}
-
- // for [databind#403]
- public void testEmptyStringFailForPrimitives() throws IOException
- {
- _verifyEmptyStringFailForPrimitives("booleanValue");
- _verifyEmptyStringFailForPrimitives("byteValue");
- _verifyEmptyStringFailForPrimitives("charValue");
- _verifyEmptyStringFailForPrimitives("shortValue");
- _verifyEmptyStringFailForPrimitives("intValue");
- _verifyEmptyStringFailForPrimitives("longValue");
- _verifyEmptyStringFailForPrimitives("floatValue");
- _verifyEmptyStringFailForPrimitives("doubleValue");
- }
/*
/**********************************************************
@@ -722,18 +709,18 @@ public class JDKScalarsTest
final String JSON_WITH_NULL = "[ null ]";
final String SIMPLE_NAME = "`"+cls.getSimpleName()+"`";
final ObjectReader readerCoerceOk = MAPPER.readerFor(cls);
- final ObjectReader readerNoCoerce = readerCoerceOk
+ final ObjectReader readerNoNulls = readerCoerceOk
.with(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
Object ob = readerCoerceOk.forType(cls).readValue(JSON_WITH_NULL);
assertEquals(1, Array.getLength(ob));
assertEquals(defValue, Array.get(ob, 0));
try {
- readerNoCoerce.readValue(JSON_WITH_NULL);
+ readerNoNulls.readValue(JSON_WITH_NULL);
fail("Should not pass");
} catch (JsonMappingException e) {
verifyException(e, "Cannot coerce `null`");
- verifyException(e, "as content of type "+SIMPLE_NAME);
+ verifyException(e, "to element of "+SIMPLE_NAME);
}
if (testEmptyString) {
@@ -741,12 +728,14 @@ public class JDKScalarsTest
assertEquals(1, Array.getLength(ob));
assertEquals(defValue, Array.get(ob, 0));
+ final ObjectReader readerNoEmpty = MAPPER_NO_COERCION.readerFor(cls);
try {
- readerNoCoerce.readValue(EMPTY_STRING_JSON);
+ readerNoEmpty.readValue(EMPTY_STRING_JSON);
fail("Should not pass");
} catch (JsonMappingException e) {
- verifyException(e, "Cannot coerce empty String (\"\")");
- verifyException(e, "as content of type "+SIMPLE_NAME);
+ // 07-Jun-2020, tatu: during transition, two acceptable alternatives
+ verifyException(e, "Cannot coerce `null` to", "Cannot coerce empty String (\"\")");
+ verifyException(e, "element of "+SIMPLE_NAME);
}
}
}
@@ -782,11 +771,11 @@ public class JDKScalarsTest
// char[] is special, cannot use generalized test here
// _testInvalidStringCoercionFail(char[].class);
- _testInvalidStringCoercionFail(short[].class);
- _testInvalidStringCoercionFail(int[].class);
- _testInvalidStringCoercionFail(long[].class);
- _testInvalidStringCoercionFail(float[].class);
- _testInvalidStringCoercionFail(double[].class);
+ _testInvalidStringCoercionFail(short[].class, "short");
+ _testInvalidStringCoercionFail(int[].class, "int");
+ _testInvalidStringCoercionFail(long[].class, "long");
+ _testInvalidStringCoercionFail(float[].class, "float");
+ _testInvalidStringCoercionFail(double[].class, "double");
}
private void _testInvalidStringCoercionFail(Class<?> cls) throws IOException
@@ -801,9 +790,38 @@ public class JDKScalarsTest
try {
MAPPER.readerFor(cls).readValue(JSON);
- fail("Should not pass");
+ fail("Should MismatchedInputException pass");
} catch (JsonMappingException e) {
verifyException(e, "Cannot deserialize value of type `"+targetTypeName+"` from String \"foobar\"");
}
}
+
+ /*
+ /**********************************************************
+ /* Tests for mismatch: JSON Object for scalars (not supported
+ /* for JSON
+ /**********************************************************
+ */
+
+ public void testFailForScalarFromObject() throws Exception
+ {
+ _testFailForNumberFromObject(Byte.TYPE);
+ _testFailForNumberFromObject(Short.TYPE);
+ _testFailForNumberFromObject(Long.TYPE);
+ _testFailForNumberFromObject(Float.TYPE);
+ _testFailForNumberFromObject(Double.TYPE);
+ _testFailForNumberFromObject(BigInteger.class);
+ _testFailForNumberFromObject(BigDecimal.class);
+ }
+
+ private void _testFailForNumberFromObject(Class<?> targetType) throws Exception
+ {
+ try {
+ MAPPER.readValue(a2q("{'value':12}"), targetType);
+ fail("Should not pass");
+ } catch (MismatchedInputException e) {
+ verifyException(e, "from Object value");
+ verifyException(e, ClassUtil.getClassDescription(targetType));
+ }
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
index b4e5892bd..9af210d3c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/JDKStringLikeTypesTest.java
@@ -138,10 +138,6 @@ public class JDKStringLikeTypesTest extends BaseMapTest
MAPPER.readValue(quote("fi_FI_savo"), Locale.class));
assertEquals(new Locale("en", "US"),
MAPPER.readValue(quote("en-US"), Locale.class));
-
- // [databind#1123]
- Locale loc = MAPPER.readValue(quote(""), Locale.class);
- assertSame(Locale.ROOT, loc);
}
public void testCharSequence() throws IOException
@@ -261,14 +257,9 @@ public class JDKStringLikeTypesTest extends BaseMapTest
final URI value = new URI("http://foo.com");
assertEquals(value, reader.readValue("\""+value.toString()+"\""));
- // Also: empty String should be handled properly
- URI result = reader.readValue(quote(""));
- assertNotNull(result);
- assertEquals(URI.create(""), result);
-
// and finally: broken URI should give proper failure
try {
- result = reader.readValue(quote("a b"));
+ URI result = reader.readValue(quote("a b"));
fail("Should not accept malformed URI, instead got: "+result);
} catch (InvalidFormatException e) {
verifyException(e, "not a valid textual representation");
@@ -303,9 +294,9 @@ public class JDKStringLikeTypesTest extends BaseMapTest
public void testUUID() throws Exception
{
- final ObjectMapper mapper = objectMapper();
-
final String NULL_UUID = "00000000-0000-0000-0000-000000000000";
+ final ObjectReader r = MAPPER.readerFor(UUID.class);
+
// first, couple of generated UUIDs:
for (String value : new String[] {
"76e6d183-5f68-4afa-b94a-922c1fdb83f8",
@@ -315,12 +306,10 @@ public class JDKStringLikeTypesTest extends BaseMapTest
"82994ac2-7b23-49f2-8cc5-e24cf6ed77be",
"00000007-0000-0000-0000-000000000000"
}) {
-
- mapper.disable(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
-
UUID uuid = UUID.fromString(value);
assertEquals(uuid,
- mapper.readValue(quote(value), UUID.class));
+ r.without(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS)
+ .readValue(quote(value)));
}
// then use templating; note that these are not exactly valid UUIDs
// wrt spec (type bits etc), but JDK UUID should deal ok
@@ -330,13 +319,13 @@ public class JDKStringLikeTypesTest extends BaseMapTest
for (int i = 0; i < chars.length(); ++i) {
String value = TEMPL.replace('0', chars.charAt(i));
assertEquals(UUID.fromString(value).toString(),
- mapper.readValue(quote(value), UUID.class).toString());
+ r.readValue(quote(value)).toString());
}
// also: see if base64 encoding works as expected
String base64 = Base64Variants.getDefaultVariant().encode(new byte[16]);
assertEquals(UUID.fromString(NULL_UUID),
- mapper.readValue(quote(base64), UUID.class));
+ r.readValue(quote(base64)));
}
public void testUUIDInvalid() throws Exception
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestGenericMapDeser.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapWithGenericValuesDeserTest.java
index e18dd2575..db6ad7700 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestGenericMapDeser.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/MapWithGenericValuesDeserTest.java
@@ -1,4 +1,4 @@
-package com.fasterxml.jackson.databind.deser;
+package com.fasterxml.jackson.databind.deser.jdk;
import java.util.*;
@@ -9,7 +9,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.type.TypeFactory;
@SuppressWarnings("serial")
-public class TestGenericMapDeser
+public class MapWithGenericValuesDeserTest
extends BaseMapTest
{
/*
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/VoidProperties2675Test.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/VoidProperties2675Test.java
new file mode 100644
index 000000000..1aae71209
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/VoidProperties2675Test.java
@@ -0,0 +1,61 @@
+package com.fasterxml.jackson.databind.deser.jdk;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+
+// [databind#2675]: Void-valued "properties"
+public class VoidProperties2675Test extends BaseMapTest
+{
+ static class VoidBean {
+ protected Void value;
+
+ public Void getValue() { return null; }
+
+// public void setValue(Void v) { }
+ }
+
+ /*
+ /**********************************************************************
+ /* Test methods
+ /**********************************************************************
+ */
+
+ private final ObjectMapper DEFAULT_MAPPER = sharedMapper();
+
+ private final ObjectMapper VOID_MAPPER = jsonMapperBuilder()
+ .enable(MapperFeature.ALLOW_VOID_VALUED_PROPERTIES)
+ .build();
+
+ public void testVoidBeanSerialization() throws Exception
+ {
+ // By default (2.x), not enabled:
+ try {
+ DEFAULT_MAPPER.writeValueAsString(new VoidBean());
+ fail("Should not pass");
+ } catch (InvalidDefinitionException e) {
+ verifyException(e, "no properties discovered");
+ }
+
+ // but when enabled
+ assertEquals("{\"value\":null}", VOID_MAPPER.writeValueAsString(new VoidBean()));
+ }
+
+ public void testVoidBeanDeserialization() throws Exception {
+ final String DOC = "{\"value\":null}";
+ VoidBean result;
+
+ // By default (2.x), not enabled:
+ try {
+ result = DEFAULT_MAPPER.readValue(DOC, VoidBean.class);
+ fail("Should not pass");
+ } catch (UnrecognizedPropertyException e) {
+ verifyException(e, "Unrecognized field \"value\"");
+ }
+
+ // but when enabled
+ result = VOID_MAPPER.readValue(DOC, VoidBean.class);
+ assertNotNull(result);
+ assertNull(result.getValue());
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java b/src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java
index 536a5b428..7e19c9a4c 100644
--- a/src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/exc/ExceptionDeserializationTest.java
@@ -157,7 +157,7 @@ public class ExceptionDeserializationTest
mapper.readValue(value, IOException.class);
fail("Exception not thrown when attempting to deserialize an IOException wrapped in a single value array with UNWRAP_SINGLE_VALUE_ARRAYS disabled");
} catch (JsonMappingException exp2) {
- verifyException(exp2, "out of START_ARRAY");
+ verifyException(exp2, "from Array value (token `JsonToken.START_ARRAY`)");
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/interop/DateJava8FallbacksTest.java b/src/test/java/com/fasterxml/jackson/databind/interop/DateJava8FallbacksTest.java
new file mode 100644
index 000000000..37fd4e79c
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/interop/DateJava8FallbacksTest.java
@@ -0,0 +1,45 @@
+package com.fasterxml.jackson.databind.interop;
+
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
+
+// [databind#2683]: add fallback handling for Java 8 date/time types, to
+// prevent accidental serialization as POJOs, as well as give more information
+// on deserialization attempts
+//
+// @since 2.12
+public class DateJava8FallbacksTest extends BaseMapTest
+{
+ private final ObjectMapper MAPPER = newJsonMapper();
+
+ private final OffsetDateTime DATETIME_EPOCH = OffsetDateTime.ofInstant(Instant.ofEpochSecond(0L),
+ ZoneOffset.of("Z"));
+
+ // Test to prevent serialization as POJO, without Java 8 date/time module:
+ public void testPreventSerialization() throws Exception
+ {
+ try {
+ String json = MAPPER.writerWithDefaultPrettyPrinter()
+ .writeValueAsString(DATETIME_EPOCH);
+ fail("Should not pass, wrote out as\n: "+json);
+ } catch (InvalidDefinitionException e) {
+ verifyException(e, "Java 8 date/time type `java.time.OffsetDateTime` not supported by default");
+ verifyException(e, "add Module \"com.fasterxml.jackson.datatype:jackson-datatype-jsr310\"");
+ }
+ }
+
+ public void testBetterDeserializationError() throws Exception
+ {
+ try {
+ OffsetDateTime result = MAPPER.readValue(" 0 ", OffsetDateTime.class);
+ fail("Not expecting to pass, resulted in: "+result);
+ } catch (InvalidDefinitionException e) {
+ verifyException(e, "Java 8 date/time type `java.time.OffsetDateTime` not supported by default");
+ verifyException(e, "add Module \"com.fasterxml.jackson.datatype:jackson-datatype-jsr310\"");
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestMultipleTypeNames.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestMultipleTypeNames.java
new file mode 100644
index 000000000..021dd1cb2
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestMultipleTypeNames.java
@@ -0,0 +1,136 @@
+package com.fasterxml.jackson.databind.jsontype;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
+
+import java.util.List;
+
+// Tests for [databind#2761] (and [annotations#171]
+public class TestMultipleTypeNames extends BaseMapTest
+{
+ private final ObjectMapper MAPPER = newJsonMapper();
+
+ // common classes
+ static class MultiTypeName { }
+
+ static class A extends MultiTypeName {
+ private long x;
+ public long getX() { return x; }
+ }
+
+ static class B extends MultiTypeName {
+ private float y;
+ public float getY() { return y; }
+ }
+
+ // data for test 1
+ static class WrapperForNamesTest {
+ private List<BaseForNamesTest> base;
+ public List<BaseForNamesTest> getBase() { return base; }
+ }
+
+ static class BaseForNamesTest {
+ private String type;
+ public String getType() { return type; }
+
+ @JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
+ property = "type"
+ )
+ @JsonSubTypes(value = {
+ @JsonSubTypes.Type(value = A.class, names = "a"),
+ @JsonSubTypes.Type(value = B.class, names = {"b","c"}),
+ })
+ private MultiTypeName data;
+ public MultiTypeName getData() { return data; }
+ }
+
+ static class WrapperForNameAndNamesTest {
+ private List<BaseForNameAndNamesTest> base;
+ public List<BaseForNameAndNamesTest> getBase() { return base; }
+ }
+
+ static class BaseForNameAndNamesTest {
+ private String type;
+ public String getType() { return type; }
+
+ @JsonTypeInfo(
+ use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
+ property = "type"
+ )
+ @JsonSubTypes(value = {
+ @JsonSubTypes.Type(value = A.class, name = "a"),
+ @JsonSubTypes.Type(value = B.class, names = {"b","c"}),
+ })
+ private MultiTypeName data;
+ public MultiTypeName getData() { return data; }
+ }
+
+ /*
+ /**********************************************************
+ /* Test methods
+ /**********************************************************
+ */
+
+ public void testOnlyNames() throws Exception
+ {
+ String json;
+ WrapperForNamesTest w;
+
+ // TC 1 : all KV serialisation
+ json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
+ w = MAPPER.readValue(json, WrapperForNamesTest.class);
+ assertNotNull(w);
+ assertEquals(3, w.base.size());
+ assertTrue(w.base.get(0).data instanceof A);
+ assertEquals(5l, ((A) w.base.get(0).data).x);
+ assertTrue(w.base.get(1).data instanceof B);
+ assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
+ assertTrue(w.base.get(2).data instanceof B);
+ assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
+
+
+ // TC 2 : incorrect serialisation
+ json = "{\"data\": [{\"type\":\"a\", \"data\": {\"x\": 2.2}}, {\"type\":\"b\", \"data\": {\"y\": 5.3}}, {\"type\":\"c\", \"data\": {\"y\": 9.8}}]}";
+ try {
+ MAPPER.readValue(json, WrapperForNamesTest.class);
+ fail("This serialisation should fail 'coz of x being float");
+ } catch (UnrecognizedPropertyException e) {
+ verifyException(e, "Unrecognized field \"data\"");
+ }
+ }
+
+ public void testNameAndNames() throws Exception
+ {
+ String json;
+ WrapperForNameAndNamesTest w;
+
+ // TC 1 : all KV serialisation
+ json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
+ w = MAPPER.readValue(json, WrapperForNameAndNamesTest.class);
+ assertNotNull(w);
+ assertEquals(3, w.base.size());
+ assertTrue(w.base.get(0).data instanceof A);
+ assertEquals(5l, ((A) w.base.get(0).data).x);
+ assertTrue(w.base.get(1).data instanceof B);
+ assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
+ assertTrue(w.base.get(2).data instanceof B);
+ assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
+
+
+ // TC 2 : incorrect serialisation
+ json = "{\"data\": [{\"type\":\"a\", \"data\": {\"x\": 2.2}}, {\"type\":\"b\", \"data\": {\"y\": 5.3}}, {\"type\":\"c\", \"data\": {\"y\": 9.8}}]}";
+ try {
+ MAPPER.readValue(json, WrapperForNameAndNamesTest.class);
+ fail("This serialisation should fail 'coz of x being float");
+ } catch (UnrecognizedPropertyException e) {
+ verifyException(e, "Unrecognized field \"data\"");
+ }
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
index c6fa2bb35..4557e0840 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestSubtypes.java
@@ -4,12 +4,9 @@ import com.fasterxml.jackson.core.Version;
import java.util.*;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.JsonTypeName;
+import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
-import com.fasterxml.jackson.databind.JsonMappingException;
+
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.exc.InvalidTypeIdException;
@@ -95,7 +92,9 @@ public class TestSubtypes extends com.fasterxml.jackson.databind.BaseMapTest
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="type")
@JsonSubTypes({ @JsonSubTypes.Type(ImplX.class),
- @JsonSubTypes.Type(ImplY.class) })
+ @JsonSubTypes.Type(ImplY.class),
+ @JsonSubTypes.Type(ImplAbs.class)
+ })
static abstract class BaseX { }
@JsonTypeName("x")
@@ -111,6 +110,11 @@ public class TestSubtypes extends com.fasterxml.jackson.databind.BaseMapTest
public int y;
}
+ // for [databind#919] testing
+ @JsonTypeName("abs")
+ abstract static class ImplAbs extends BaseX {
+ }
+
// [databind#663]
static class AtomicWrapper {
public BaseX value;
@@ -372,16 +376,16 @@ public class TestSubtypes extends com.fasterxml.jackson.databind.BaseMapTest
bean = mapper.readValue("{\"#type\":\"foobar\"}", SuperTypeWithoutDefault.class);
assertEquals(DefaultImpl505.class, bean.getClass());
assertEquals(0, ((DefaultImpl505) bean).a);
-
}
-
+
public void testErrorMessage() throws Exception {
ObjectMapper mapper = new ObjectMapper();
try {
mapper.readValue("{ \"type\": \"z\"}", BaseX.class);
fail("Should have failed");
- } catch (JsonMappingException e) {
- verifyException(e, "known type ids =");
+ } catch (InvalidTypeIdException e) {
+ verifyException(e, "Could not resolve type id 'z' as a subtype of");
+ verifyException(e, "known type ids = [x, y]");
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
index 15d95f82d..8a066f6d2 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestWithGenerics.java
@@ -126,7 +126,7 @@ public class TestWithGenerics extends BaseMapTest
otherAnimal = a2;
}
}
-
+
/*
/**********************************************************
/* Unit tests
diff --git a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
index 362039391..dbb738ca7 100644
--- a/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/misc/CaseInsensitiveDeserTest.java
@@ -9,6 +9,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
public class CaseInsensitiveDeserTest extends BaseMapTest
{
@@ -93,13 +94,31 @@ public class CaseInsensitiveDeserTest extends BaseMapTest
}
}
+ // [databind#1886]: allow case-insensitivity by default on a class
+ @JsonFormat(with={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES })
+ static class CaseInsensitiveRole {
+ public String ID;
+ public String Name;
+ }
+
+ // [databind#1886]: allow case-insensitivity by default on a class
+ static class CaseInsensitiveRoleContainer {
+ public CaseInsensitiveRole role;
+ }
+
+ // [databind#1886]: ... but also overrides
+ static class CaseSensitiveRoleContainer {
+ @JsonFormat(without={ JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES })
+ public CaseInsensitiveRole role;
+ }
+
/*
/********************************************************
/* Test methods
/********************************************************
*/
- private final ObjectMapper MAPPER = new ObjectMapper();
+ private final ObjectMapper MAPPER = newJsonMapper();
private final ObjectMapper INSENSITIVE_MAPPER = jsonMapperBuilder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
.build();
@@ -158,7 +177,7 @@ public class CaseInsensitiveDeserTest extends BaseMapTest
}
// And allow config overrides too
- public void testCaseInsensitiveWithClassFormat() throws Exception
+ public void testCaseInsensitiveViaConfigOverride() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.configOverride(Role.class)
@@ -181,4 +200,34 @@ public class CaseInsensitiveDeserTest extends BaseMapTest
assertNotNull(result.getItems());
assertEquals(1, result.getItems().size());
}
+
+
+ // [databind#1886]: allow case-insensitivity by default on a class
+ public void testCaseInsensitiveViaClassAnnotation() throws Exception
+ {
+ final String CONTAINED = aposToQuotes("{'role': {'id':'3','name':'Bob'}}");
+
+ // First: via wrapper/container:
+ CaseInsensitiveRoleContainer cont = MAPPER.readValue(CONTAINED,
+ CaseInsensitiveRoleContainer.class);
+ assertEquals("3", cont.role.ID);
+ assertEquals("Bob", cont.role.Name);
+
+ // second: directly as root value
+ CaseInsensitiveRole role = MAPPER.readValue
+ (aposToQuotes("{'id':'12','name':'Billy'}"),
+ CaseInsensitiveRole.class);
+ assertEquals("12", role.ID);
+ assertEquals("Billy", role.Name);
+
+ // and finally, more complicated; should be possible to force sensitivity:
+ try {
+ /*CaseSensitiveRoleContainer r =*/ MAPPER.readValue(CONTAINED,
+ CaseSensitiveRoleContainer.class);
+ fail("Should not pass");
+ } catch (UnrecognizedPropertyException e) {
+ verifyException(e, "Unrecognized ");
+ verifyException(e, "\"id\"");
+ }
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
index e129dcf56..08bd47d98 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/ArrayNodeTest.java
@@ -359,7 +359,7 @@ public class ArrayNodeTest
mapper.readValue(" 123 ", ArrayNode.class);
fail("Should not pass");
} catch (MismatchedInputException e) {
- verifyException(e, "out of VALUE_NUMBER_INT token");
+ verifyException(e, "from Integer value (token `JsonToken.VALUE_NUMBER_INT`)");
}
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java b/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
index 260e93ecc..cd15ee687 100644
--- a/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/node/ObjectNodeTest.java
@@ -463,7 +463,7 @@ public class ObjectNodeTest
mapper.readValue("[ 1, 2, 3 ]", ObjectNode.class);
fail("Should not pass");
} catch (MismatchedInputException e) {
- verifyException(e, "out of START_ARRAY token");
+ verifyException(e, "from Array value (token `JsonToken.START_ARRAY`)");
}
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java
index 972a5fa8f..91eda5e44 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId687Test.java
@@ -63,7 +63,7 @@ public class ObjectId687Test extends BaseMapTest
/*****************************************************
*/
- private final ObjectMapper MAPPER = objectMapper();
+ private final ObjectMapper MAPPER = newJsonMapper();
// for [databind#687]
public void testSerializeDeserializeWithCreator() throws IOException {
diff --git a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
index af173eede..171f1ded1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/objectid/ObjectId825BTest.java
@@ -136,10 +136,15 @@ public class ObjectId825BTest extends BaseMapTest
private static final long serialVersionUID = 1L;
}
+ /*
+ /*****************************************************
+ /* Test methods
+ /*****************************************************
+ */
+
public void testFull825() throws Exception
{
final ObjectMapper mapper = jsonMapperBuilder()
- .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
.activateDefaultTyping(NoCheckSubTypeValidator.instance,
ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE)
.build();
diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
index 10baa8ef6..e1cd38d69 100644
--- a/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
+++ b/src/test/java/com/fasterxml/jackson/databind/ser/TestArraySerialization.java
@@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.*;
public class TestArraySerialization
extends BaseMapTest
{
- private final ObjectMapper MAPPER = newJsonMapper();
+ private final ObjectMapper MAPPER = sharedMapper();
public void testLongStringArray() throws Exception
{
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java
deleted file mode 100644
index 71aba3253..000000000
--- a/src/test/java/com/fasterxml/jackson/databind/struct/EmptyArrayAsNullTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-package com.fasterxml.jackson.databind.struct;
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import java.util.*;
-
-import com.fasterxml.jackson.core.type.TypeReference;
-import com.fasterxml.jackson.databind.*;
-
-/**
- * Tests to verify implementation of [databind#540]; also for
- * follow up work of:
- *
- * - [databind#994]
- */
-public class EmptyArrayAsNullTest extends BaseMapTest
-{
- private final ObjectMapper MAPPER = new ObjectMapper();
- private final ObjectReader DEFAULT_READER = MAPPER.reader();
- private final ObjectReader READER_WITH_ARRAYS = DEFAULT_READER
- .with(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT);
-
- static class Bean {
- public String a = "foo";
- }
-
- final static String EMPTY_ARRAY = " [\n]";
-
- /*
- /**********************************************************
- /* Test methods, settings
- /**********************************************************
- */
-
- public void testSettings() {
- assertFalse(MAPPER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
- assertFalse(DEFAULT_READER.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
- assertTrue(READER_WITH_ARRAYS.isEnabled(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT));
- }
-
- /*
- /**********************************************************
- /* Test methods, POJOs
- /**********************************************************
- */
-
- // [databind#540]
- public void testPOJOFromEmptyArray() throws Exception
- {
- // first, verify default settings which do not accept empty Array
- try {
- DEFAULT_READER.forType(Bean.class)
- .readValue(EMPTY_ARRAY);
- fail("Should not accept Empty Array for POJO by default");
- } catch (JsonMappingException e) {
- verifyException(e, "START_ARRAY token");
- assertValidLocation(e.getLocation());
- }
-
- // should be ok to enable dynamically:
- Bean result = READER_WITH_ARRAYS.forType(Bean.class)
- .readValue(EMPTY_ARRAY);
- assertNull(result);
- }
-
- /*
- /**********************************************************
- /* Test methods, Maps
- /**********************************************************
- */
-
- public void testMapFromEmptyArray() throws Exception
- {
- // first, verify default settings which do not accept empty Array
- try {
- DEFAULT_READER.forType(Map.class)
- .readValue(EMPTY_ARRAY);
- fail("Should not accept Empty Array for Map by default");
- } catch (JsonMappingException e) {
- verifyException(e, "START_ARRAY token");
- }
- // should be ok to enable dynamically:
- Map<?,?> result = READER_WITH_ARRAYS.forType(Map.class)
- .readValue(EMPTY_ARRAY);
- assertNull(result);
- }
-
- public void testEnumMapFromEmptyArray() throws Exception
- {
-
- EnumMap<?,?> result2 = READER_WITH_ARRAYS.forType(new TypeReference<EnumMap<ABC,String>>() { })
- .readValue(EMPTY_ARRAY);
- assertNull(result2);
- }
-
- /*
- /**********************************************************
- /* Test methods, primitives/wrappers
- /**********************************************************
- */
-
- public void testWrapperFromEmptyArray() throws Exception
- {
- _testNullWrapper(Boolean.class);
- _testNullWrapper(Byte.class);
- _testNullWrapper(Character.class);
- _testNullWrapper(Short.class);
- _testNullWrapper(Integer.class);
- _testNullWrapper(Long.class);
- _testNullWrapper(Float.class);
- _testNullWrapper(Double.class);
- }
-
- /*
- /**********************************************************
- /* Test methods, other
- /**********************************************************
- */
-
- public void testNullStringFromEmptyArray() throws Exception {
- _testNullWrapper(String.class);
- }
-
- public void testNullEnumFromEmptyArray() throws Exception {
- _testNullWrapper(ABC.class);
- }
-
- public void testStdJdkTypesFromEmptyArray() throws Exception
- {
- _testNullWrapper(BigInteger.class);
- _testNullWrapper(BigDecimal.class);
-
- _testNullWrapper(UUID.class);
-
- _testNullWrapper(Date.class);
- _testNullWrapper(Calendar.class);
- }
-
- /*
- /**********************************************************
- /* Helper methods
- /**********************************************************
- */
-
- private void _testNullWrapper(Class<?> cls) throws Exception
- {
- Object result = READER_WITH_ARRAYS.forType(cls).readValue(EMPTY_ARRAY);
- assertNull(result);
- }
-}
diff --git a/src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java b/src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java
index a13988e90..cb06cd559 100644
--- a/src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java
+++ b/src/test/java/com/fasterxml/jackson/databind/struct/UnwrapSingleArrayScalarsTest.java
@@ -80,7 +80,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
.readValue("{\"v\":[3]}");
fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
} catch (MismatchedInputException e) {
- verifyException(e, "Cannot deserialize instance of `int`");
+ verifyException(e, "Cannot deserialize value of type `int`");
}
ObjectReader r = UNWRAPPING_READER.forType(IntBean.class);
@@ -117,7 +117,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
noUnwrapR.readValue("{\"v\":[3]}");
fail("Did not throw exception when reading a value from a single value array");
} catch (MismatchedInputException e) {
- verifyException(e, "Cannot deserialize instance of `long`");
+ verifyException(e, "Cannot deserialize value of type `long`");
}
LongBean result = unwrapR.readValue("{\"v\":[3]}");
@@ -154,7 +154,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
noUnwrapR.readValue("{\"v\":[" + value + "]}");
fail("Did not throw exception when reading a value from a single value array");
} catch (MismatchedInputException e) {
- verifyException(e, "Cannot deserialize instance of `double`");
+ verifyException(e, "Cannot deserialize value of type `double`");
}
DoubleBean result = unwrapR.readValue("{\"v\":[" + value + "]}");
@@ -359,8 +359,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
NO_UNWRAPPING_READER.readValue("[\""+value+"\"]", String.class);
fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String");
} catch (MismatchedInputException exp) {
- verifyException(exp, "Cannot deserialize");
- verifyException(exp, "out of START_ARRAY");
+ _verifyNoDeserFromArray(exp);
}
try {
@@ -385,8 +384,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
r.readValue("[" + value.toString() + "]");
fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
} catch (MismatchedInputException exp) {
- verifyException(exp, "Cannot deserialize");
- verifyException(exp, "out of START_ARRAY");
+ _verifyNoDeserFromArray(exp);
}
r = UNWRAPPING_READER.forType(BigDecimal.class);
@@ -411,8 +409,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
NO_UNWRAPPING_READER.readValue("[" + value.toString() + "]", BigInteger.class);
fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
} catch (MismatchedInputException exp) {
- verifyException(exp, "Cannot deserialize");
- verifyException(exp, "out of START_ARRAY");
+ _verifyNoDeserFromArray(exp);
}
result = UNWRAPPING_READER.readValue("[" + value.toString() + "]", BigInteger.class);
@@ -438,7 +435,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
.readValue("[" + quote(String.class.getName()) + "]");
fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element");
} catch (MismatchedInputException e) {
- verifyException(e, "out of START_ARRAY token");
+ _verifyNoDeserFromArray(e);
}
_verifyMultiValueArrayFail("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]",
@@ -456,7 +453,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
.readValue("[\""+value.toString()+"\"]");
fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
} catch (MismatchedInputException e) {
- verifyException(e, "out of START_ARRAY token");
+ _verifyNoDeserFromArray(e);
}
_verifyMultiValueArrayFail("[\""+value.toString()+"\",\""+value.toString()+"\"]", URI.class);
@@ -471,7 +468,7 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
.readValue("[" + quote(uuidStr) + "]");
fail("Exception was not thrown as expected");
} catch (MismatchedInputException e) {
- verifyException(e, "out of START_ARRAY token");
+ _verifyNoDeserFromArray(e);
}
assertEquals(uuid,
UNWRAPPING_READER.forType(UUID.class)
@@ -485,6 +482,12 @@ public class UnwrapSingleArrayScalarsTest extends BaseMapTest
/**********************************************************
*/
+ private void _verifyNoDeserFromArray(Exception e) {
+ verifyException(e, "Cannot deserialize");
+ verifyException(e, "from Array value");
+ verifyException(e, "JsonToken.START_ARRAY");
+ }
+
private void _verifyMultiValueArrayFail(String input, Class<?> type) throws IOException {
try {
UNWRAPPING_READER.forType(type).readValue(input);
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
index def53ce11..5487a4c7f 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java
@@ -280,7 +280,12 @@ public class TestJavaType
assertTrue(t.hasContentType());
assertEquals(Long.class, t.getContentType().getRawClass());
- // 26-Mar-2020, tatu: [databind#2019] suggest this should be 1...
-// assertEquals(1, t.containedTypeCount());
+ // 26-Mar-2020, tatu: [databind#2019] made this work
+ assertEquals(1, t.containedTypeCount());
+ TypeBindings bindings = t.getBindings();
+ assertEquals(1, bindings.size());
+ assertEquals(refdType, bindings.getBoundType(0));
+ // Should we even verify this or not?
+ assertEquals("V", bindings.getBoundName(0));
}
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
index e78c15d1a..dc326d5d1 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
@@ -160,7 +160,7 @@ public class TestTypeFactory
{
TypeFactory tf = TypeFactory.defaultInstance();
// first, simple class based
- JavaType t = tf.constructParametrizedType(ArrayList.class, Collection.class, String.class); // ArrayList<String>
+ final JavaType t = tf.constructParametrizedType(ArrayList.class, Collection.class, String.class); // ArrayList<String>
assertEquals(CollectionType.class, t.getClass());
JavaType strC = tf.constructType(String.class);
assertEquals(1, t.containedTypeCount());
@@ -176,6 +176,13 @@ public class TestTypeFactory
assertEquals(t, t2.containedType(1));
assertNull(t2.containedType(2));
+ // [databind#921]: using type bindings
+ JavaType t3 = tf.constructParametricType(HashSet.class, t.getBindings()); // HashSet<String>
+ assertEquals(CollectionType.class, t3.getClass());
+ assertEquals(1, t3.containedTypeCount());
+ assertEquals(strC, t3.containedType(0));
+ assertNull(t3.containedType(1));
+
// and then custom generic type as well
JavaType custom = tf.constructParametrizedType(SingleArgGeneric.class, SingleArgGeneric.class,
String.class);
@@ -184,10 +191,24 @@ public class TestTypeFactory
assertEquals(strC, custom.containedType(0));
assertNull(custom.containedType(1));
+ // and then custom generic type from TypeBindings ([databind#921])
+ JavaType custom2 = tf.constructParametricType(SingleArgGeneric.class, t.getBindings());
+ assertEquals(SimpleType.class, custom2.getClass());
+ assertEquals(1, custom2.containedTypeCount());
+ assertEquals(strC, custom2.containedType(0));
+ assertNull(custom2.containedType(1));
+
// should also be able to access variable name:
assertEquals("X", custom.containedTypeName(0));
+ }
- // And finally, ensure that we can't create invalid combinations
+ @SuppressWarnings("deprecation")
+ public void testInvalidParametricTypes()
+ {
+ final TypeFactory tf = TypeFactory.defaultInstance();
+ final JavaType strC = tf.constructType(String.class);
+
+ // ensure that we can't create invalid combinations
try {
// Maps must take 2 type parameters, not just one
tf.constructParametrizedType(Map.class, Map.class, strC);
@@ -202,7 +223,7 @@ public class TestTypeFactory
verifyException(e, "Cannot create TypeBindings for class ");
}
}
-
+
/**
* Test for checking that canonical name handling works ok
*/
diff --git a/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java b/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java
deleted file mode 100644
index 54c6d6a76..000000000
--- a/src/test/java/com/fasterxml/jackson/failing/BuilderWithIgnored1214Test.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.databind.*;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
-
-public class BuilderWithIgnored1214Test extends BaseMapTest
-{
- @JsonDeserialize(builder = TestObject1214.Builder.class)
- @JsonIgnoreProperties(ignoreUnknown = true)
- static class TestObject1214 {
- final String property1;
-
- private TestObject1214(Builder builder) {
- property1 = builder.property1;
- }
-
- public static Builder builder() {
- return new Builder();
- }
-
- public String getProperty1() {
- return property1;
- }
-
- static class Builder {
-
- private String property1;
-
- public Builder withProperty1(String p1) {
- property1 = p1;
- return this;
- }
-
- public TestObject1214 build() {
- return new TestObject1214(this);
- }
- }
- }
-
- public void testUnknown1214() throws Exception
- {
- ObjectMapper mapper = new ObjectMapper();
- TestObject1214 value = mapper.readValue(aposToQuotes
- ("{'property1':'a', 'property2':'b'}"),
- TestObject1214.class);
- assertEquals("a", value.property1);
- }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/JDKNumberDeser2644Test.java b/src/test/java/com/fasterxml/jackson/failing/JDKNumberDeser2644Test.java
deleted file mode 100644
index d92300a35..000000000
--- a/src/test/java/com/fasterxml/jackson/failing/JDKNumberDeser2644Test.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import java.math.BigDecimal;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonSubTypes;
-import com.fasterxml.jackson.annotation.JsonTypeInfo;
-import com.fasterxml.jackson.annotation.JsonUnwrapped;
-import com.fasterxml.jackson.databind.*;
-
-// Tests for
-//
-// [databind#2644]
-// [databind#2785]
-public class JDKNumberDeser2644Test extends BaseMapTest
-{
- // [databind#2644]
- static class NodeRoot2644 {
- public String type;
-
- @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type")
- @JsonSubTypes(value = {
- @JsonSubTypes.Type(value = NodeParent2644.class, name = "NodeParent")
- })
- public Node2644 node;
- }
-
- public static class NodeParent2644 extends Node2644 { }
-
- public static abstract class Node2644 {
- @JsonProperty("amount")
- BigDecimal val;
-
- public BigDecimal getVal() {
- return val;
- }
-
- public void setVal(BigDecimal val) {
- this.val = val;
- }
- }
-
- // [databind#2785]
- static class BigDecimalHolder2785 {
- public BigDecimal value;
- }
-
- static class NestedBigDecimalHolder2785 {
- @JsonUnwrapped
- public BigDecimalHolder2785 holder;
- }
-
- // [databind#2644]
- public void testBigDecimalSubtypes() throws Exception
- {
- ObjectMapper mapper = newJsonMapper();
-
- // NOTE: uncommenting this does work around the issue:
-// mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
- mapper.registerSubtypes(NodeParent2644.class);
-
- NodeRoot2644 root = mapper.readValue(
- "{\"type\": \"NodeParent\",\"node\": {\"amount\": 9999999999999999.99} }",
- NodeRoot2644.class
- );
-
- assertEquals(new BigDecimal("9999999999999999.99"), root.node.getVal());
- }
-
- // [databind#2785]
-
- public void testBigDecimalUnwrapped() throws Exception
- {
- final ObjectMapper mapper = newJsonMapper();
- // mapper.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
- final String JSON = "{\"value\": 5.00}";
-
- // first simple working case:
- BigDecimalHolder2785 holder = mapper.readValue(JSON, BigDecimalHolder2785.class);
- assertEquals(new BigDecimal("5.00"), holder.value);
-
- // and then one that doesn't
- NestedBigDecimalHolder2785 result = mapper.readValue(JSON, NestedBigDecimalHolder2785.class);
- assertEquals(new BigDecimal("5.00"), result.holder.value);
- }
-}
diff --git a/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java b/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
index 192feb4ec..a2e18f0ff 100644
--- a/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
+++ b/src/test/java/com/fasterxml/jackson/failing/NumberNodes1770Test.java
@@ -19,7 +19,7 @@ public class NumberNodes1770Test extends BaseMapTest
final JsonNode jsonNode = MAPPER.reader()
.with(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
.readTree("7976931348623157e309");
- assertTrue(jsonNode.isBigDecimal());
+ assertTrue("Expected DecimalNode, got: "+jsonNode.getClass().getName()+": "+jsonNode, jsonNode.isBigDecimal());
// the following fails with NumberFormatException, because jsonNode is a DoubleNode with a value of POSITIVE_INFINITY
// Assert.assertTrue(jsonNode.decimalValue().compareTo(new BigDecimal("7976931348623157e309")) == 0);
}
diff --git a/src/test/java/com/fasterxml/jackson/failing/ParsingContextExtTypeId2747Test.java b/src/test/java/com/fasterxml/jackson/failing/ParsingContextExtTypeId2747Test.java
new file mode 100644
index 000000000..3bc900f5a
--- /dev/null
+++ b/src/test/java/com/fasterxml/jackson/failing/ParsingContextExtTypeId2747Test.java
@@ -0,0 +1,65 @@
+package com.fasterxml.jackson.failing;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.annotation.*;
+
+import com.fasterxml.jackson.core.*;
+
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+
+public class ParsingContextExtTypeId2747Test extends BaseMapTest
+{
+ static class Wrapper {
+ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type",
+ include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
+ public Tag wrapped;
+
+ public String type;
+ }
+
+ @JsonSubTypes(@JsonSubTypes.Type(Location.class))
+ interface Tag {}
+
+ @JsonTypeName("location")
+ @JsonDeserialize(using = LocationDeserializer.class)
+ static class Location implements Tag
+ {
+ String value;
+
+ protected Location() { }
+ Location(String v) { value = v; }
+ }
+
+ static class LocationDeserializer extends JsonDeserializer<Location>
+ {
+ @Override
+ public Location deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
+ {
+ p.skipChildren();
+ return new Location(getCurrentLocationAsString(p));
+ }
+ }
+
+ static String getCurrentLocationAsString(JsonParser p)
+ {
+ // This suffices to give actual path
+ return p.getParsingContext().pathAsPointer().toString();
+ }
+
+ // [databind#2747]
+ public void testLocationAccessWithExtTypeId() throws Exception
+ {
+ ObjectReader objectReader = newJsonMapper().readerFor(Wrapper.class);
+
+ Wrapper wrapper = objectReader.readValue("{" +
+ "\"type\":\"location\"," +
+ "\"wrapped\": 1" +
+ "}");
+ // expecting wrapper.wrapped.value == "wrapped" but is "wrapped[1]"
+ // due to way `ExternalTypeHandler` exposes value as if "wrapper-array" was used for
+ // type id, value
+ assertEquals("/wrapped", ((Location) wrapper.wrapped).value);
+ }
+}
diff --git a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java b/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
deleted file mode 100644
index 09b3226b7..000000000
--- a/src/test/java/com/fasterxml/jackson/failing/TestUnknownProperty426.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.annotation.*;
-
-import com.fasterxml.jackson.databind.*;
-
-/**
- * Unit tests for checking handling of unknown properties
- */
-public class TestUnknownProperty426 extends BaseMapTest
-{
- // For [databind#426]
- @JsonIgnoreProperties({ "userId" })
- static class User {
- public String firstName;
- Integer userId;
-
- public void setUserId(CharSequence id) {
- // 21-Dec-2015, tatu: With a fix in 2.7, use of String would not
- // trigger the problem, so use CharSequence...
- setUserId(Integer.valueOf(id.toString()));
- }
-
- public Integer getUserId() {
- return userId;
- }
-
- public void setUserId(Integer v) {
- this.userId = v;
- }
- }
-
- /*
- /**********************************************************
- /* Test methods
- /**********************************************************
- */
-
- private final ObjectMapper MAPPER = new ObjectMapper();
-
- // Aside from [databind#426], also relevant: [databind#1044]?
- public void testIssue426() throws Exception
- {
- final String JSON = aposToQuotes("{'userId': 9, 'firstName': 'Mike' }");
- User result = MAPPER.readerFor(User.class).readValue(JSON);
- assertNotNull(result);
- assertEquals("Mike", result.firstName);
- }
-}
-
diff --git a/src/test/java/com/fasterxml/jackson/failing/VoidProperties2675Test.java b/src/test/java/com/fasterxml/jackson/failing/VoidProperties2675Test.java
deleted file mode 100644
index c7727eb48..000000000
--- a/src/test/java/com/fasterxml/jackson/failing/VoidProperties2675Test.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.fasterxml.jackson.failing;
-
-import com.fasterxml.jackson.databind.*;
-
-public class VoidProperties2675Test extends BaseMapTest
-{
- static class VoidBean {
- public Void getValue() { return null; }
- }
-
- /*
- /**********************************************************************
- /* Test methods
- /**********************************************************************
- */
-
- private final ObjectMapper MAPPER = new ObjectMapper();
-
- public void testVoidBean() throws Exception {
- final String EXP = "{\"value\":null}";
- assertEquals(EXP, MAPPER.writeValueAsString(new VoidBean()));
- VoidBean result = MAPPER.readValue(EXP, VoidBean.class);
- assertNotNull(result);
- }
-}