• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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