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