• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.struct;
2 
3 import java.io.IOException;
4 import java.io.StringReader;
5 import java.math.BigDecimal;
6 import java.math.BigInteger;
7 import java.net.URI;
8 import java.util.UUID;
9 
10 import com.fasterxml.jackson.databind.BaseMapTest;
11 import com.fasterxml.jackson.databind.DeserializationFeature;
12 import com.fasterxml.jackson.databind.ObjectMapper;
13 import com.fasterxml.jackson.databind.ObjectReader;
14 import com.fasterxml.jackson.databind.exc.MismatchedInputException;
15 
16 public class UnwrapSingleArrayScalarsTest extends BaseMapTest
17 {
18     static class BooleanBean {
19         public boolean v;
20     }
21 
22     static class IntBean {
23         public int v;
24     }
25 
26     static class LongBean {
27         public long v;
28     }
29 
30     static class DoubleBean {
31         public double v;
32     }
33 
34     private final ObjectMapper MAPPER = new ObjectMapper();
35 
36     private final ObjectReader NO_UNWRAPPING_READER = MAPPER.reader();
37     private final ObjectReader UNWRAPPING_READER = MAPPER.reader()
38             .with(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
39 
40     /*
41     /**********************************************************
42     /* Tests for boolean
43     /**********************************************************
44      */
45 
testBooleanPrimitiveArrayUnwrap()46     public void testBooleanPrimitiveArrayUnwrap() throws Exception
47     {
48         // [databind#381]
49         final ObjectReader r = UNWRAPPING_READER.forType(BooleanBean.class);
50         BooleanBean result = r.readValue(new StringReader("{\"v\":[true]}"));
51         assertTrue(result.v);
52 
53         _verifyMultiValueArrayFail("[{\"v\":[true,true]}]", BooleanBean.class);
54 
55         result = r.readValue("{\"v\":[null]}");
56         assertNotNull(result);
57         assertFalse(result.v);
58 
59         result = r.readValue("[{\"v\":[null]}]");
60         assertNotNull(result);
61         assertFalse(result.v);
62 
63         boolean[] array = UNWRAPPING_READER.forType(boolean[].class)
64                 .readValue(new StringReader("[ [ null ] ]"));
65         assertNotNull(array);
66         assertEquals(1, array.length);
67         assertFalse(array[0]);
68     }
69 
70     /*
71     /**********************************************************
72     /* Single-element as array tests, numbers
73     /**********************************************************
74      */
75 
testIntPrimitiveArrayUnwrap()76     public void testIntPrimitiveArrayUnwrap() throws Exception
77     {
78         try {
79             NO_UNWRAPPING_READER.forType(IntBean.class)
80                 .readValue("{\"v\":[3]}");
81             fail("Did not throw exception when reading a value from a single value array with the UNWRAP_SINGLE_VALUE_ARRAYS feature disabled");
82         } catch (MismatchedInputException e) {
83             verifyException(e, "Cannot deserialize value of type `int`");
84         }
85 
86         ObjectReader r = UNWRAPPING_READER.forType(IntBean.class);
87         IntBean result = r.readValue("{\"v\":[3]}");
88         assertEquals(3, result.v);
89 
90         result = r.readValue("[{\"v\":[3]}]");
91         assertEquals(3, result.v);
92 
93         try {
94             r.readValue("[{\"v\":[3,3]}]");
95             fail("Did not throw exception while reading a value from a multi value array with UNWRAP_SINGLE_VALUE_ARRAY feature enabled");
96         } catch (MismatchedInputException e) {
97             verifyException(e, "more than one value");
98         }
99 
100         result = r.readValue("{\"v\":[null]}");
101         assertNotNull(result);
102         assertEquals(0, result.v);
103 
104         int[] array = UNWRAPPING_READER.forType(int[].class).readValue("[ [ null ] ]");
105         assertNotNull(array);
106         assertEquals(1, array.length);
107         assertEquals(0, array[0]);
108 
109     }
110 
testLongPrimitiveArrayUnwrap()111     public void testLongPrimitiveArrayUnwrap() throws Exception
112     {
113         final ObjectReader unwrapR = UNWRAPPING_READER.forType(LongBean.class);
114         final ObjectReader noUnwrapR = NO_UNWRAPPING_READER.forType(LongBean.class);
115 
116         try {
117             noUnwrapR.readValue("{\"v\":[3]}");
118             fail("Did not throw exception when reading a value from a single value array");
119         } catch (MismatchedInputException e) {
120             verifyException(e, "Cannot deserialize value of type `long`");
121         }
122 
123         LongBean result = unwrapR.readValue("{\"v\":[3]}");
124         assertEquals(3, result.v);
125 
126         result = unwrapR.readValue("[{\"v\":[3]}]");
127         assertEquals(3, result.v);
128 
129         try {
130             unwrapR.readValue("[{\"v\":[3,3]}]");
131             fail("Did not throw exception while reading a value from a multi value array");
132         } catch (MismatchedInputException e) {
133             verifyException(e, "more than one value");
134         }
135 
136         result = unwrapR.readValue("{\"v\":[null]}");
137         assertNotNull(result);
138         assertEquals(0, result.v);
139 
140         long[] array = unwrapR.forType(long[].class)
141                 .readValue("[ [ null ] ]");
142         assertNotNull(array);
143         assertEquals(1, array.length);
144         assertEquals(0, array[0]);
145     }
146 
testDoubleAsArray()147     public void testDoubleAsArray() throws Exception
148     {
149         final ObjectReader unwrapR = UNWRAPPING_READER.forType(DoubleBean.class);
150         final ObjectReader noUnwrapR = NO_UNWRAPPING_READER.forType(DoubleBean.class);
151 
152         final double value = 0.016;
153         try {
154             noUnwrapR.readValue("{\"v\":[" + value + "]}");
155             fail("Did not throw exception when reading a value from a single value array");
156         } catch (MismatchedInputException e) {
157             verifyException(e, "Cannot deserialize value of type `double`");
158         }
159 
160         DoubleBean result = unwrapR.readValue("{\"v\":[" + value + "]}");
161         assertEquals(value, result.v);
162 
163         result = unwrapR.readValue("[{\"v\":[" + value + "]}]");
164         assertEquals(value, result.v);
165 
166         try {
167             unwrapR.readValue("[{\"v\":[" + value + "," + value + "]}]");
168             fail("Did not throw exception while reading a value from a multi value array");
169         } catch (MismatchedInputException e) {
170             verifyException(e, "more than one value");
171         }
172 
173         result = unwrapR.readValue("{\"v\":[null]}");
174         assertNotNull(result);
175         assertEquals(0d, result.v);
176 
177         double[] array = unwrapR.forType(double[].class)
178                 .readValue("[ [ null ] ]");
179         assertNotNull(array);
180         assertEquals(1, array.length);
181         assertEquals(0d, array[0]);
182     }
183 
testSingleElementScalarArrays()184     public void testSingleElementScalarArrays() throws Exception {
185         final int intTest = 932832;
186         final double doubleTest = 32.3234;
187         final long longTest = 2374237428374293423L;
188         final short shortTest = (short) intTest;
189         final float floatTest = 84.3743f;
190         final byte byteTest = (byte) 43;
191         final char charTest = 'c';
192 
193         final int intValue = UNWRAPPING_READER.readValue(asArray(intTest), Integer.TYPE);
194         assertEquals(intTest, intValue);
195         final Integer integerWrapperValue = UNWRAPPING_READER.readValue(asArray(Integer.valueOf(intTest)), Integer.class);
196         assertEquals(Integer.valueOf(intTest), integerWrapperValue);
197 
198         final double doubleValue = UNWRAPPING_READER.readValue(asArray(doubleTest), Double.class);
199         assertEquals(doubleTest, doubleValue);
200         final Double doubleWrapperValue = UNWRAPPING_READER.readValue(asArray(Double.valueOf(doubleTest)), Double.class);
201         assertEquals(Double.valueOf(doubleTest), doubleWrapperValue);
202 
203         final long longValue = UNWRAPPING_READER.readValue(asArray(longTest), Long.TYPE);
204         assertEquals(longTest, longValue);
205         final Long longWrapperValue = UNWRAPPING_READER.readValue(asArray(Long.valueOf(longTest)), Long.class);
206         assertEquals(Long.valueOf(longTest), longWrapperValue);
207 
208         final short shortValue = UNWRAPPING_READER.readValue(asArray(shortTest), Short.TYPE);
209         assertEquals(shortTest, shortValue);
210         final Short shortWrapperValue = UNWRAPPING_READER.readValue(asArray(Short.valueOf(shortTest)), Short.class);
211         assertEquals(Short.valueOf(shortTest), shortWrapperValue);
212 
213         final float floatValue = UNWRAPPING_READER.readValue(asArray(floatTest), Float.TYPE);
214         assertEquals(floatTest, floatValue);
215         final Float floatWrapperValue = UNWRAPPING_READER.readValue(asArray(Float.valueOf(floatTest)), Float.class);
216         assertEquals(Float.valueOf(floatTest), floatWrapperValue);
217 
218         final byte byteValue = UNWRAPPING_READER.readValue(asArray(byteTest), Byte.TYPE);
219         assertEquals(byteTest, byteValue);
220         final Byte byteWrapperValue = UNWRAPPING_READER.readValue(asArray(Byte.valueOf(byteTest)), Byte.class);
221         assertEquals(Byte.valueOf(byteTest), byteWrapperValue);
222 
223         final char charValue = UNWRAPPING_READER.readValue(asArray(quote(String.valueOf(charTest))), Character.TYPE);
224         assertEquals(charTest, charValue);
225         final Character charWrapperValue = UNWRAPPING_READER.readValue(asArray(quote(String.valueOf(charTest))), Character.class);
226         assertEquals(Character.valueOf(charTest), charWrapperValue);
227 
228         final boolean booleanTrueValue = UNWRAPPING_READER.readValue(asArray(true), Boolean.TYPE);
229         assertTrue(booleanTrueValue);
230 
231         final boolean booleanFalseValue = UNWRAPPING_READER.readValue(asArray(false), Boolean.TYPE);
232         assertFalse(booleanFalseValue);
233 
234         final Boolean booleanWrapperTrueValue = UNWRAPPING_READER.readValue(asArray(Boolean.valueOf(true)), Boolean.class);
235         assertEquals(Boolean.TRUE, booleanWrapperTrueValue);
236     }
237 
testSingleElementArrayDisabled()238     public void testSingleElementArrayDisabled() throws Exception {
239         try {
240             NO_UNWRAPPING_READER.readValue("[42]", Integer.class);
241             fail("Single value array didn't throw an exception");
242         } catch (MismatchedInputException exp) {
243             //Exception was thrown correctly
244         }
245         try {
246             NO_UNWRAPPING_READER.readValue("[42]", Integer.TYPE);
247             fail("Single value array didn't throw an exception");
248         } catch (MismatchedInputException exp) {
249             //Exception was thrown correctly
250         }
251         try {
252             NO_UNWRAPPING_READER.readValue("[42342342342342]", Long.class);
253             fail("Single value array didn't throw an exception");
254         } catch (MismatchedInputException exp) {
255             //Exception was thrown correctly
256         }
257         try {
258             NO_UNWRAPPING_READER.readValue("[42342342342342342]", Long.TYPE);
259             fail("Single value array didn't throw an exception");
260         } catch (MismatchedInputException exp) {
261             //Exception was thrown correctly
262         }
263 
264         try {
265             NO_UNWRAPPING_READER.readValue("[42]", Short.class);
266             fail("Single value array didn't throw an exception");
267         } catch (MismatchedInputException exp) {
268             //Exception was thrown correctly
269         }
270         try {
271             NO_UNWRAPPING_READER.readValue("[42]", Short.TYPE);
272             fail("Single value array didn't throw an exception");
273         } catch (MismatchedInputException exp) {
274             //Exception was thrown correctly
275         }
276 
277         try {
278             NO_UNWRAPPING_READER.readValue("[327.2323]", Float.class);
279             fail("Single value array didn't throw an exception");
280         } catch (MismatchedInputException exp) {
281             //Exception was thrown correctly
282         }
283         try {
284             NO_UNWRAPPING_READER.readValue("[82.81902]", Float.TYPE);
285             fail("Single value array didn't throw an exception");
286         } catch (MismatchedInputException exp) {
287             //Exception was thrown correctly
288         }
289 
290         try {
291             NO_UNWRAPPING_READER.readValue("[22]", Byte.class);
292             fail("Single value array didn't throw an exception");
293         } catch (MismatchedInputException exp) {
294             //Exception was thrown correctly
295         }
296         try {
297             NO_UNWRAPPING_READER.readValue("[22]", Byte.TYPE);
298             fail("Single value array didn't throw an exception");
299         } catch (MismatchedInputException exp) {
300             //Exception was thrown correctly
301         }
302 
303         try {
304             NO_UNWRAPPING_READER.readValue("['d']", Character.class);
305             fail("Single value array didn't throw an exception");
306         } catch (MismatchedInputException exp) {
307             //Exception was thrown correctly
308         }
309         try {
310             NO_UNWRAPPING_READER.readValue("['d']", Character.TYPE);
311             fail("Single value array didn't throw an exception");
312         } catch (MismatchedInputException exp) {
313             //Exception was thrown correctly
314         }
315 
316         try {
317             NO_UNWRAPPING_READER.readValue("[true]", Boolean.class);
318             fail("Single value array didn't throw an exception");
319         } catch (MismatchedInputException exp) {
320             //Exception was thrown correctly
321         }
322         try {
323             NO_UNWRAPPING_READER.readValue("[true]", Boolean.TYPE);
324             fail("Single value array didn't throw an exception");
325         } catch (MismatchedInputException exp) {
326             //Exception was thrown correctly
327         }
328     }
329 
testMultiValueArrayException()330     public void testMultiValueArrayException() throws IOException {
331         _verifyMultiValueArrayFail("[42,42]", Integer.class);
332         _verifyMultiValueArrayFail("[42,42]", Integer.TYPE);
333         _verifyMultiValueArrayFail("[42342342342342,42342342342342]", Long.class);
334         _verifyMultiValueArrayFail("[42342342342342342,42342342342342]", Long.TYPE);
335         _verifyMultiValueArrayFail("[42,42]", Short.class);
336         _verifyMultiValueArrayFail("[42,42]", Short.TYPE);
337         _verifyMultiValueArrayFail("[22,23]", Byte.class);
338         _verifyMultiValueArrayFail("[22,23]", Byte.TYPE);
339         _verifyMultiValueArrayFail("[327.2323,327.2323]", Float.class);
340         _verifyMultiValueArrayFail("[82.81902,327.2323]", Float.TYPE);
341         _verifyMultiValueArrayFail("[42.273,42.273]", Double.class);
342         _verifyMultiValueArrayFail("[42.2723,42.273]", Double.TYPE);
343         _verifyMultiValueArrayFail(asArray(quote("c") + ","  + quote("d")), Character.class);
344         _verifyMultiValueArrayFail(asArray(quote("c") + ","  + quote("d")), Character.TYPE);
345         _verifyMultiValueArrayFail("[true,false]", Boolean.class);
346         _verifyMultiValueArrayFail("[true,false]", Boolean.TYPE);
347     }
348 
349     /*
350     /**********************************************************
351     /* Simple non-primitive types
352     /**********************************************************
353      */
354 
testSingleStringWrapped()355     public void testSingleStringWrapped() throws Exception
356     {
357         String value = "FOO!";
358         try {
359             NO_UNWRAPPING_READER.readValue("[\""+value+"\"]", String.class);
360             fail("Exception not thrown when attempting to unwrap a single value 'String' array into a simple String");
361         } catch (MismatchedInputException exp) {
362             _verifyNoDeserFromArray(exp);
363         }
364 
365         try {
366             UNWRAPPING_READER.forType(String.class)
367                 .readValue("[\""+value+"\",\""+value+"\"]");
368             fail("Exception not thrown when attempting to unwrap a single value 'String' array that contained more than one value into a simple String");
369         } catch (MismatchedInputException exp) {
370             verifyException(exp, "Attempted to unwrap");
371         }
372         String result = UNWRAPPING_READER.forType(String.class)
373                 .readValue("[\""+value+"\"]");
374         assertEquals(value, result);
375     }
376 
testBigDecimal()377     public void testBigDecimal() throws Exception
378     {
379         BigDecimal value = new BigDecimal("0.001");
380         ObjectReader r = NO_UNWRAPPING_READER.forType(BigDecimal.class);
381         BigDecimal result = r.readValue(value.toString());
382         assertEquals(value, result);
383         try {
384             r.readValue("[" + value.toString() + "]");
385             fail("Exception was not thrown when attempting to read a single value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
386         } catch (MismatchedInputException exp) {
387             _verifyNoDeserFromArray(exp);
388         }
389 
390         r = UNWRAPPING_READER.forType(BigDecimal.class);
391         result = r.readValue("[" + value.toString() + "]");
392         assertEquals(value, result);
393 
394         try {
395             r.readValue("[" + value.toString() + "," + value.toString() + "]");
396             fail("Exception was not thrown when attempting to read a muti value array of BigDecimal when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
397         } catch (MismatchedInputException exp) {
398             verifyException(exp, "Attempted to unwrap");
399         }
400     }
401 
testBigInteger()402     public void testBigInteger() throws Exception
403     {
404         BigInteger value = new BigInteger("-1234567890123456789012345567809");
405         BigInteger result = NO_UNWRAPPING_READER.readValue(value.toString(), BigInteger.class);
406         assertEquals(value, result);
407 
408         try {
409             NO_UNWRAPPING_READER.readValue("[" + value.toString() + "]", BigInteger.class);
410             fail("Exception was not thrown when attempting to read a single value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is disabled");
411         } catch (MismatchedInputException exp) {
412             _verifyNoDeserFromArray(exp);
413         }
414 
415         result = UNWRAPPING_READER.readValue("[" + value.toString() + "]", BigInteger.class);
416         assertEquals(value, result);
417 
418         try {
419             UNWRAPPING_READER.readValue("[" + value.toString() + "," + value.toString() + "]", BigInteger.class);
420             fail("Exception was not thrown when attempting to read a multi-value array of BigInteger when UNWRAP_SINGLE_VALUE_ARRAYS feature is enabled");
421         } catch (MismatchedInputException exp) {
422             verifyException(exp, "Attempted to unwrap");
423         }
424     }
425 
testClassAsArray()426     public void testClassAsArray() throws Exception
427     {
428         Class<?> result = UNWRAPPING_READER
429                     .forType(Class.class)
430                     .readValue(quote(String.class.getName()));
431         assertEquals(String.class, result);
432 
433         try {
434             NO_UNWRAPPING_READER.forType(Class.class)
435                 .readValue("[" + quote(String.class.getName()) + "]");
436             fail("Did not throw exception when UNWRAP_SINGLE_VALUE_ARRAYS feature was disabled and attempted to read a Class array containing one element");
437         } catch (MismatchedInputException e) {
438             _verifyNoDeserFromArray(e);
439         }
440 
441         _verifyMultiValueArrayFail("[" + quote(Object.class.getName()) + "," + quote(Object.class.getName()) +"]",
442                 Class.class);
443         result = UNWRAPPING_READER.forType(Class.class)
444                 .readValue("[" + quote(String.class.getName()) + "]");
445         assertEquals(String.class, result);
446     }
447 
testURIAsArray()448     public void testURIAsArray() throws Exception
449     {
450         final URI value = new URI("http://foo.com");
451         try {
452             NO_UNWRAPPING_READER.forType(URI.class)
453                 .readValue("[\""+value.toString()+"\"]");
454             fail("Did not throw exception for single value array when UNWRAP_SINGLE_VALUE_ARRAYS is disabled");
455         } catch (MismatchedInputException e) {
456             _verifyNoDeserFromArray(e);
457         }
458 
459         _verifyMultiValueArrayFail("[\""+value.toString()+"\",\""+value.toString()+"\"]", URI.class);
460     }
461 
testUUIDAsArray()462     public void testUUIDAsArray() throws Exception
463     {
464         final String uuidStr = "76e6d183-5f68-4afa-b94a-922c1fdb83f8";
465         UUID uuid = UUID.fromString(uuidStr);
466         try {
467             NO_UNWRAPPING_READER.forType(UUID.class)
468                 .readValue("[" + quote(uuidStr) + "]");
469             fail("Exception was not thrown as expected");
470         } catch (MismatchedInputException e) {
471             _verifyNoDeserFromArray(e);
472         }
473         assertEquals(uuid,
474                 UNWRAPPING_READER.forType(UUID.class)
475                     .readValue("[" + quote(uuidStr) + "]"));
476         _verifyMultiValueArrayFail("[" + quote(uuidStr) + "," + quote(uuidStr) + "]", UUID.class);
477     }
478 
479     /*
480     /**********************************************************
481     /* Helper methods
482     /**********************************************************
483      */
484 
_verifyNoDeserFromArray(Exception e)485     private void _verifyNoDeserFromArray(Exception e) {
486         verifyException(e, "Cannot deserialize");
487         verifyException(e, "from Array value");
488         verifyException(e, "JsonToken.START_ARRAY");
489     }
490 
_verifyMultiValueArrayFail(String input, Class<?> type)491     private void _verifyMultiValueArrayFail(String input, Class<?> type) throws IOException {
492         try {
493             UNWRAPPING_READER.forType(type).readValue(input);
494             fail("Single value array didn't throw an exception");
495         } catch (MismatchedInputException e) {
496             verifyException(e, "Attempted to unwrap");
497         }
498     }
499 
asArray(Object value)500     private static String asArray(Object value) {
501         return "["+value+"]";
502     }
503 }
504