aboutsummaryrefslogtreecommitdiff
path: root/src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java')
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/convert/CoerceEmptyArrayTest.java255
1 files changed, 255 insertions, 0 deletions
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`)");
+ }
+ }
+}