1 package com.fasterxml.jackson.databind; 2 3 import java.io.IOException; 4 import java.io.StringWriter; 5 import java.util.*; 6 7 import com.fasterxml.jackson.annotation.JsonCreator; 8 import com.fasterxml.jackson.annotation.JsonProperty; 9 10 import com.fasterxml.jackson.core.*; 11 import com.fasterxml.jackson.core.json.JsonReadFeature; 12 13 import com.fasterxml.jackson.databind.cfg.ContextAttributes; 14 import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; 15 import com.fasterxml.jackson.databind.exc.MismatchedInputException; 16 import com.fasterxml.jackson.databind.json.JsonMapper; 17 import com.fasterxml.jackson.databind.node.ArrayNode; 18 import com.fasterxml.jackson.databind.node.JsonNodeFactory; 19 import com.fasterxml.jackson.databind.node.ObjectNode; 20 21 public class ObjectReaderTest extends BaseMapTest 22 { 23 final JsonMapper MAPPER = JsonMapper.builder().build(); 24 25 static class POJO { 26 public Map<String, Object> name; 27 } 28 29 /* 30 /********************************************************** 31 /* Test methods, simple read/write with defaults 32 /********************************************************** 33 */ 34 testSimpleViaParser()35 public void testSimpleViaParser() throws Exception 36 { 37 final String JSON = "[1]"; 38 JsonParser p = MAPPER.createParser(JSON); 39 Object ob = MAPPER.readerFor(Object.class) 40 .readValue(p); 41 p.close(); 42 assertTrue(ob instanceof List<?>); 43 } 44 testSimpleAltSources()45 public void testSimpleAltSources() throws Exception 46 { 47 final String JSON = "[1]"; 48 final byte[] BYTES = JSON.getBytes("UTF-8"); 49 Object ob = MAPPER.readerFor(Object.class) 50 .readValue(BYTES); 51 assertTrue(ob instanceof List<?>); 52 53 ob = MAPPER.readerFor(Object.class) 54 .readValue(BYTES, 0, BYTES.length); 55 assertTrue(ob instanceof List<?>); 56 assertEquals(1, ((List<?>) ob).size()); 57 58 // but also failure mode(s) 59 try { 60 MAPPER.readerFor(Object.class) 61 .readValue(new byte[0]); 62 fail("Should not pass"); 63 } catch (MismatchedInputException e) { 64 verifyException(e, "No content to map due to end-of-input"); 65 } 66 } 67 68 // [databind#2693]: convenience read methods: testReaderForArrayOf()69 public void testReaderForArrayOf() throws Exception 70 { 71 Object value = MAPPER.readerForArrayOf(ABC.class) 72 .readValue("[ \"A\", \"C\" ]"); 73 assertEquals(ABC[].class, value.getClass()); 74 ABC[] abcs = (ABC[]) value; 75 assertEquals(2, abcs.length); 76 assertEquals(ABC.A, abcs[0]); 77 assertEquals(ABC.C, abcs[1]); 78 } 79 80 // [databind#2693]: convenience read methods: testReaderForListOf()81 public void testReaderForListOf() throws Exception 82 { 83 Object value = MAPPER.readerForListOf(ABC.class) 84 .readValue("[ \"B\", \"C\" ]"); 85 assertEquals(ArrayList.class, value.getClass()); 86 assertEquals(Arrays.asList(ABC.B, ABC.C), value); 87 } 88 89 // [databind#2693]: convenience read methods: testReaderForMapOf()90 public void testReaderForMapOf() throws Exception 91 { 92 Object value = MAPPER.readerForMapOf(ABC.class) 93 .readValue("{\"key\" : \"B\" }"); 94 assertEquals(LinkedHashMap.class, value.getClass()); 95 assertEquals(Collections.singletonMap("key", ABC.B), value); 96 } 97 testNodeHandling()98 public void testNodeHandling() throws Exception 99 { 100 JsonNodeFactory nodes = new JsonNodeFactory(true); 101 ObjectReader r = MAPPER.reader().with(nodes); 102 // but also no further changes if attempting again 103 assertSame(r, r.with(nodes)); 104 assertTrue(r.createArrayNode().isArray()); 105 assertTrue(r.createObjectNode().isObject()); 106 } 107 108 /* 109 /********************************************************** 110 /* Test methods, some alternative JSON settings 111 /********************************************************** 112 */ 113 testParserFeaturesComments()114 public void testParserFeaturesComments() throws Exception 115 { 116 final String JSON = "[ /* foo */ 7 ]"; 117 // default won't accept comments, let's change that: 118 ObjectReader reader = MAPPER.readerFor(int[].class) 119 .with(JsonReadFeature.ALLOW_JAVA_COMMENTS); 120 121 int[] value = reader.readValue(JSON); 122 assertNotNull(value); 123 assertEquals(1, value.length); 124 assertEquals(7, value[0]); 125 126 // but also can go back 127 try { 128 reader.without(JsonReadFeature.ALLOW_JAVA_COMMENTS).readValue(JSON); 129 fail("Should not have passed"); 130 } catch (JsonProcessingException e) { 131 verifyException(e, "foo"); 132 } 133 } 134 testParserFeaturesCtrlChars()135 public void testParserFeaturesCtrlChars() throws Exception 136 { 137 String FIELD = "a\tb"; 138 String VALUE = "\t"; 139 String JSON = "{ "+quote(FIELD)+" : "+quote(VALUE)+"}"; 140 Map<?, ?> result; 141 142 // First: by default, unescaped control characters should not work 143 try { 144 result = MAPPER.readValue(JSON, Map.class); 145 fail("Should not pass with defaylt settings"); 146 } catch (JsonParseException e) { 147 verifyException(e, "Illegal unquoted character"); 148 } 149 150 // But both ObjectReader: 151 result = MAPPER.readerFor(Map.class) 152 .with(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS) 153 .readValue(JSON); 154 assertEquals(1, result.size()); 155 156 // and new mapper should work 157 ObjectMapper mapper2 = JsonMapper.builder() 158 .enable(JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS) 159 .build(); 160 result = mapper2.readerFor(Map.class) 161 .readValue(JSON); 162 assertEquals(1, result.size()); 163 } 164 165 /* 166 /********************************************************** 167 /* Test methods, config setting verification 168 /********************************************************** 169 */ 170 testFeatureSettings()171 public void testFeatureSettings() throws Exception 172 { 173 ObjectReader r = MAPPER.reader(); 174 assertFalse(r.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)); 175 assertFalse(r.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 176 177 r = r.withoutFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, 178 DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); 179 assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)); 180 assertFalse(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); 181 r = r.withFeatures(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, 182 DeserializationFeature.FAIL_ON_INVALID_SUBTYPE); 183 assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)); 184 assertTrue(r.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); 185 186 // alternative method too... can't recall why two 187 assertSame(r, r.with(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, 188 DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)); 189 190 // and another one 191 assertSame(r, r.with(r.getConfig())); 192 193 // and with StreamReadFeatures 194 r = MAPPER.reader(); 195 assertFalse(r.isEnabled(StreamReadFeature.IGNORE_UNDEFINED)); 196 ObjectReader r2 = r.with(StreamReadFeature.IGNORE_UNDEFINED); 197 assertTrue(r2.isEnabled(StreamReadFeature.IGNORE_UNDEFINED)); 198 ObjectReader r3 = r2.without(StreamReadFeature.IGNORE_UNDEFINED); 199 assertFalse(r3.isEnabled(StreamReadFeature.IGNORE_UNDEFINED)); 200 } 201 testFeatureSettingsDeprecated()202 public void testFeatureSettingsDeprecated() throws Exception 203 { 204 final ObjectReader r = MAPPER.reader(); 205 assertFalse(r.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 206 207 assertTrue(r.with(JsonParser.Feature.IGNORE_UNDEFINED) 208 .isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 209 assertFalse(r.without(JsonParser.Feature.IGNORE_UNDEFINED) 210 .isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 211 212 // and then variants 213 assertFalse(r.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION)); 214 ObjectReader r2 = r.withFeatures(JsonParser.Feature.IGNORE_UNDEFINED, 215 JsonParser.Feature.STRICT_DUPLICATE_DETECTION); 216 assertTrue(r2.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION)); 217 assertTrue(r2.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 218 219 ObjectReader r3 = r2.withoutFeatures(JsonParser.Feature.IGNORE_UNDEFINED, 220 JsonParser.Feature.STRICT_DUPLICATE_DETECTION); 221 assertFalse(r3.isEnabled(JsonParser.Feature.STRICT_DUPLICATE_DETECTION)); 222 assertFalse(r3.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED)); 223 } 224 testMiscSettings()225 public void testMiscSettings() throws Exception 226 { 227 ObjectReader r = MAPPER.reader(); 228 assertSame(MAPPER.getFactory(), r.getFactory()); 229 230 JsonFactory f = new JsonFactory(); 231 r = r.with(f); 232 assertSame(f, r.getFactory()); 233 assertSame(r, r.with(f)); 234 235 assertNotNull(r.getTypeFactory()); 236 assertNull(r.getInjectableValues()); 237 238 r = r.withAttributes(Collections.emptyMap()); 239 ContextAttributes attrs = r.getAttributes(); 240 assertNotNull(attrs); 241 assertNull(attrs.getAttribute("abc")); 242 assertSame(r, r.withoutAttribute("foo")); 243 244 ObjectReader newR = r.forType(MAPPER.constructType(String.class)); 245 assertNotSame(r, newR); 246 assertSame(newR, newR.forType(String.class)); 247 248 DeserializationProblemHandler probH = new DeserializationProblemHandler() { 249 }; 250 newR = r.withHandler(probH); 251 assertNotSame(r, newR); 252 assertSame(newR, newR.withHandler(probH)); 253 r = newR; 254 } 255 256 @SuppressWarnings("deprecation") testDeprecatedSettings()257 public void testDeprecatedSettings() throws Exception 258 { 259 ObjectReader r = MAPPER.reader(); 260 261 // and deprecated variants 262 ObjectReader newR = r.forType(MAPPER.constructType(String.class)); 263 assertSame(newR, newR.withType(String.class)); 264 assertSame(newR, newR.withType(MAPPER.constructType(String.class))); 265 266 newR = newR.withRootName(PropertyName.construct("foo")); 267 assertNotSame(r, newR); 268 assertSame(newR, newR.withRootName(PropertyName.construct("foo"))); 269 } 270 testNoPrefetch()271 public void testNoPrefetch() throws Exception 272 { 273 ObjectReader r = MAPPER.reader() 274 .without(DeserializationFeature.EAGER_DESERIALIZER_FETCH); 275 Number n = r.forType(Integer.class).readValue("123 "); 276 assertEquals(Integer.valueOf(123), n); 277 } 278 279 // @since 2.10 testGetValueType()280 public void testGetValueType() throws Exception 281 { 282 ObjectReader r = MAPPER.reader(); 283 assertNull(r.getValueType()); 284 285 r = r.forType(String.class); 286 assertEquals(MAPPER.constructType(String.class), r.getValueType()); 287 } 288 testParserConfigViaReader()289 public void testParserConfigViaReader() throws Exception 290 { 291 try (JsonParser p = MAPPER.reader() 292 .with(StreamReadFeature.STRICT_DUPLICATE_DETECTION) 293 .createParser("[ ]")) { 294 assertTrue(p.isEnabled(StreamReadFeature.STRICT_DUPLICATE_DETECTION)); 295 } 296 297 try (JsonParser p = MAPPER.reader() 298 .with(JsonReadFeature.ALLOW_JAVA_COMMENTS) 299 .createParser("[ ]")) { 300 assertTrue(p.isEnabled(JsonReadFeature.ALLOW_JAVA_COMMENTS.mappedFeature())); 301 } 302 } 303 testGeneratorConfigViaReader()304 public void testGeneratorConfigViaReader() throws Exception 305 { 306 StringWriter sw = new StringWriter(); 307 try (JsonGenerator g = MAPPER.writer() 308 .with(StreamWriteFeature.IGNORE_UNKNOWN) 309 .createGenerator(sw)) { 310 assertTrue(g.isEnabled(StreamWriteFeature.IGNORE_UNKNOWN)); 311 } 312 } 313 314 /* 315 /********************************************************** 316 /* Test methods, JsonPointer 317 /********************************************************** 318 */ 319 testNoPointerLoading()320 public void testNoPointerLoading() throws Exception { 321 final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; 322 323 JsonNode tree = MAPPER.readTree(source); 324 JsonNode node = tree.at("/foo/bar/caller"); 325 POJO pojo = MAPPER.treeToValue(node, POJO.class); 326 assertTrue(pojo.name.containsKey("value")); 327 assertEquals(1234, pojo.name.get("value")); 328 } 329 testPointerLoading()330 public void testPointerLoading() throws Exception { 331 final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; 332 333 ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); 334 335 POJO pojo = reader.readValue(source); 336 assertTrue(pojo.name.containsKey("value")); 337 assertEquals(1234, pojo.name.get("value")); 338 } 339 testPointerLoadingAsJsonNode()340 public void testPointerLoadingAsJsonNode() throws Exception { 341 final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; 342 343 ObjectReader reader = MAPPER.readerFor(POJO.class).at(JsonPointer.compile("/foo/bar/caller")); 344 345 JsonNode node = reader.readTree(source); 346 assertTrue(node.has("name")); 347 assertEquals("{\"value\":1234}", node.get("name").toString()); 348 } 349 testPointerLoadingMappingIteratorOne()350 public void testPointerLoadingMappingIteratorOne() throws Exception { 351 final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; 352 353 ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); 354 355 MappingIterator<POJO> itr = reader.readValues(source); 356 357 POJO pojo = itr.next(); 358 359 assertTrue(pojo.name.containsKey("value")); 360 assertEquals(1234, pojo.name.get("value")); 361 assertFalse(itr.hasNext()); 362 itr.close(); 363 } 364 testPointerLoadingMappingIteratorMany()365 public void testPointerLoadingMappingIteratorMany() throws Exception { 366 final String source = "{\"foo\":{\"bar\":{\"caller\":[{\"name\":{\"value\":1234}}, {\"name\":{\"value\":5678}}]}}}"; 367 368 ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); 369 370 MappingIterator<POJO> itr = reader.readValues(source); 371 372 POJO pojo = itr.next(); 373 374 assertTrue(pojo.name.containsKey("value")); 375 assertEquals(1234, pojo.name.get("value")); 376 assertTrue(itr.hasNext()); 377 378 pojo = itr.next(); 379 380 assertNotNull(pojo.name); 381 assertTrue(pojo.name.containsKey("value")); 382 assertEquals(5678, pojo.name.get("value")); 383 assertFalse(itr.hasNext()); 384 itr.close(); 385 } 386 387 // [databind#1637] testPointerWithArrays()388 public void testPointerWithArrays() throws Exception 389 { 390 final String json = aposToQuotes("{\n'wrapper1': {\n" + 391 " 'set1': ['one', 'two', 'three'],\n" + 392 " 'set2': ['four', 'five', 'six']\n" + 393 "},\n" + 394 "'wrapper2': {\n" + 395 " 'set1': ['one', 'two', 'three'],\n" + 396 " 'set2': ['four', 'five', 'six']\n" + 397 "}\n}"); 398 399 final Pojo1637 testObject = MAPPER.readerFor(Pojo1637.class) 400 .at("/wrapper1") 401 .readValue(json); 402 assertNotNull(testObject); 403 404 assertNotNull(testObject.set1); 405 assertTrue(!testObject.set1.isEmpty()); 406 407 assertNotNull(testObject.set2); 408 assertTrue(!testObject.set2.isEmpty()); 409 } 410 411 public static class Pojo1637 { 412 public Set<String> set1; 413 public Set<String> set2; 414 } 415 416 // [databind#2636] testCanPassResultToOverloadedMethod()417 public void testCanPassResultToOverloadedMethod() throws Exception { 418 final String source = "{\"foo\":{\"bar\":{\"caller\":{\"name\":{\"value\":1234}}}}}"; 419 420 ObjectReader reader = MAPPER.readerFor(POJO.class).at("/foo/bar/caller"); 421 422 process(reader.readValue(source, POJO.class)); 423 } 424 process(POJO pojo)425 void process(POJO pojo) { 426 // do nothing - just used to show that the compiler can choose the correct method overloading to invoke 427 } 428 process(String pojo)429 void process(String pojo) { 430 // do nothing - just used to show that the compiler can choose the correct method overloading to invoke 431 throw new Error(); 432 } 433 434 /* 435 /********************************************************** 436 /* Test methods, ObjectCodec 437 /********************************************************** 438 */ 439 testTreeToValue()440 public void testTreeToValue() throws Exception 441 { 442 ArrayNode n = MAPPER.createArrayNode(); 443 n.add("xyz"); 444 ObjectReader r = MAPPER.readerFor(String.class); 445 List<?> list = r.treeToValue(n, List.class); 446 assertEquals(1, list.size()); 447 } 448 testCodecUnsupportedWrites()449 public void testCodecUnsupportedWrites() throws Exception 450 { 451 ObjectReader r = MAPPER.readerFor(String.class); 452 JsonGenerator g = MAPPER.createGenerator(new StringWriter()); 453 ObjectNode n = MAPPER.createObjectNode(); 454 try { 455 r.writeTree(g, n); 456 fail("Should not pass"); 457 } catch (UnsupportedOperationException e) { 458 ; 459 } 460 try { 461 r.writeValue(g, "Foo"); 462 fail("Should not pass"); 463 } catch (UnsupportedOperationException e) { 464 ; 465 } 466 g.close(); 467 } 468 469 /* 470 /********************************************************** 471 /* Test methods, failures, other 472 /********************************************************** 473 */ 474 testMissingType()475 public void testMissingType() throws Exception 476 { 477 ObjectReader r = MAPPER.reader(); 478 try { 479 r.readValue("1"); 480 fail("Should not pass"); 481 } catch (JsonMappingException e) { 482 verifyException(e, "No value type configured"); 483 } 484 } 485 testSchema()486 public void testSchema() throws Exception 487 { 488 ObjectReader r = MAPPER.readerFor(String.class); 489 490 // Ok to try to set `null` schema, always: 491 r = r.with((FormatSchema) null); 492 493 try { 494 // but not schema that doesn't match format (no schema exists for json) 495 r = r.with(new BogusSchema()) 496 .readValue(quote("foo")); 497 498 fail("Should not pass"); 499 } catch (IllegalArgumentException e) { 500 verifyException(e, "Cannot use FormatSchema"); 501 } 502 } 503 504 // For [databind#2297] testUnknownFields()505 public void testUnknownFields() throws Exception 506 { 507 ObjectMapper mapper = JsonMapper.builder().addHandler(new DeserializationProblemHandler(){ 508 @Override 509 public boolean handleUnknownProperty(DeserializationContext ctxt, JsonParser p, JsonDeserializer<?> deserializer, Object beanOrClass, String propertyName) throws IOException { 510 p.readValueAsTree(); 511 return true; 512 } 513 }).build(); 514 A aObject = mapper.readValue("{\"unknownField\" : 1, \"knownField\": \"test\"}", A.class); 515 516 assertEquals("test", aObject.knownField); 517 } 518 519 private static class A{ 520 private String knownField; 521 522 @JsonCreator A(@sonProperty"knownField") String knownField)523 private A(@JsonProperty("knownField") String knownField) { 524 this.knownField = knownField; 525 } 526 } 527 } 528