• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind;
2 
3 import com.fasterxml.jackson.databind.module.SimpleModule;
4 import java.io.*;
5 import java.util.*;
6 
7 import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
8 import com.fasterxml.jackson.annotation.JsonInclude;
9 import com.fasterxml.jackson.annotation.JsonSetter;
10 import com.fasterxml.jackson.annotation.JsonTypeInfo;
11 import com.fasterxml.jackson.annotation.JsonTypeName;
12 import com.fasterxml.jackson.annotation.Nulls;
13 import com.fasterxml.jackson.core.*;
14 import com.fasterxml.jackson.core.json.JsonWriteFeature;
15 import com.fasterxml.jackson.core.util.MinimalPrettyPrinter;
16 
17 import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
18 import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
19 import com.fasterxml.jackson.databind.json.JsonMapper;
20 import com.fasterxml.jackson.databind.node.*;
21 
22 public class ObjectMapperTest extends BaseMapTest
23 {
24     static class Bean {
25         int value = 3;
26 
setX(int v)27         public void setX(int v) { value = v; }
28 
Bean()29         protected Bean() { }
Bean(int v)30         public Bean(int v) { value = v; }
31     }
32 
33     static class EmptyBean { }
34 
35     @SuppressWarnings("serial")
36     static class MyAnnotationIntrospector extends JacksonAnnotationIntrospector { }
37 
38     // for [databind#689]
39     @SuppressWarnings("serial")
40     static class FooPrettyPrinter extends MinimalPrettyPrinter {
FooPrettyPrinter()41         public FooPrettyPrinter() {
42             super(" /*foo*/ ");
43         }
44 
45         @Override
writeArrayValueSeparator(JsonGenerator g)46         public void writeArrayValueSeparator(JsonGenerator g) throws IOException
47         {
48             g.writeRaw(" , ");
49         }
50     }
51 
52     // for [databind#206]
53     @SuppressWarnings("serial")
54     static class NoCopyMapper extends ObjectMapper { }
55 
56     // [databind#2785]
57     @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXISTING_PROPERTY,
58             property = "packetType")
59     public interface Base2785  {
60     }
61     @JsonTypeName("myType")
62     static class Impl2785 implements Base2785 {
63     }
64 
65     private final ObjectMapper MAPPER = newJsonMapper();
66 
67     /*
68     /**********************************************************
69     /* Test methods, config
70     /**********************************************************
71      */
72 
testFactoryFeatures()73     public void testFactoryFeatures()
74     {
75         assertTrue(MAPPER.isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES));
76     }
77 
testGeneratorFeatures()78     public void testGeneratorFeatures()
79     {
80         // and also for mapper
81         JsonMapper mapper = new JsonMapper();
82         assertTrue(mapper.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
83         assertTrue(mapper.isEnabled(StreamWriteFeature.AUTO_CLOSE_TARGET));
84         assertFalse(mapper.isEnabled(JsonWriteFeature.ESCAPE_NON_ASCII));
85         assertTrue(mapper.isEnabled(JsonWriteFeature.WRITE_NAN_AS_STRINGS));
86         mapper = JsonMapper.builder()
87                 .disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM)
88                 .disable(JsonWriteFeature.WRITE_NAN_AS_STRINGS)
89                 .build();
90         assertFalse(mapper.isEnabled(StreamWriteFeature.FLUSH_PASSED_TO_STREAM));
91         assertFalse(mapper.isEnabled(JsonWriteFeature.WRITE_NAN_AS_STRINGS));
92     }
93 
testParserFeatures()94     public void testParserFeatures()
95     {
96         // and also for mapper
97         ObjectMapper mapper = new ObjectMapper();
98 
99         assertTrue(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
100         assertTrue(mapper.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
101         assertFalse(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
102 
103         mapper.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE,
104                 JsonParser.Feature.STRICT_DUPLICATE_DETECTION);
105         assertFalse(mapper.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
106         assertFalse(mapper.isEnabled(StreamReadFeature.AUTO_CLOSE_SOURCE));
107     }
108 
109     /*
110     /**********************************************************
111     /* Test methods, mapper.copy()
112     /**********************************************************
113      */
114 
115     // [databind#28]: ObjectMapper.copy()
testCopy()116     public void testCopy() throws Exception
117     {
118         ObjectMapper m = new ObjectMapper();
119         assertTrue(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
120         m.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
121         assertFalse(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
122         InjectableValues inj = new InjectableValues.Std();
123         m.setInjectableValues(inj);
124         assertFalse(m.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
125         m.enable(JsonParser.Feature.IGNORE_UNDEFINED);
126         assertTrue(m.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
127 
128         // // First: verify that handling of features is decoupled:
129 
130         ObjectMapper m2 = m.copy();
131         assertFalse(m2.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
132         m2.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
133         assertTrue(m2.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
134         assertSame(inj, m2.getInjectableValues());
135 
136         // but should NOT change the original
137         assertFalse(m.isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES));
138 
139         // nor vice versa:
140         assertFalse(m.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE));
141         assertFalse(m2.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE));
142         m.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
143         assertTrue(m.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE));
144         assertFalse(m2.isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE));
145 
146         // // Also, underlying JsonFactory instances should be distinct
147         assertNotSame(m.getFactory(), m2.getFactory());
148 
149         // [databind#2755]: also need to copy this:
150         assertNotSame(m.getSubtypeResolver(), m2.getSubtypeResolver());
151 
152         // [databind#122]: Need to ensure mix-ins are not shared
153         assertEquals(0, m.getSerializationConfig().mixInCount());
154         assertEquals(0, m2.getSerializationConfig().mixInCount());
155         assertEquals(0, m.getDeserializationConfig().mixInCount());
156         assertEquals(0, m2.getDeserializationConfig().mixInCount());
157 
158         m.addMixIn(String.class, Integer.class);
159         assertEquals(1, m.getSerializationConfig().mixInCount());
160         assertEquals(0, m2.getSerializationConfig().mixInCount());
161         assertEquals(1, m.getDeserializationConfig().mixInCount());
162         assertEquals(0, m2.getDeserializationConfig().mixInCount());
163 
164         // [databind#913]: Ensure JsonFactory Features copied
165         assertTrue(m2.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
166     }
167 
168     // [databind#1580]
testCopyOfConfigOverrides()169     public void testCopyOfConfigOverrides() throws Exception
170     {
171         ObjectMapper m = new ObjectMapper();
172         SerializationConfig config = m.getSerializationConfig();
173         assertEquals(JsonInclude.Value.empty(), config.getDefaultPropertyInclusion());
174         assertEquals(JsonSetter.Value.empty(), config.getDefaultSetterInfo());
175         assertNull(config.getDefaultMergeable());
176         VisibilityChecker<?> defaultVis = config.getDefaultVisibilityChecker();
177         assertEquals(VisibilityChecker.Std.class, defaultVis.getClass());
178 
179         // change
180         JsonInclude.Value customIncl = JsonInclude.Value.empty().withValueInclusion(JsonInclude.Include.NON_DEFAULT);
181         m.setDefaultPropertyInclusion(customIncl);
182         JsonSetter.Value customSetter = JsonSetter.Value.forValueNulls(Nulls.SKIP);
183         m.setDefaultSetterInfo(customSetter);
184         m.setDefaultMergeable(Boolean.TRUE);
185         VisibilityChecker<?> customVis = VisibilityChecker.Std.defaultInstance()
186                 .withFieldVisibility(Visibility.ANY);
187         m.setVisibility(customVis);
188         assertSame(customVis, m.getVisibilityChecker());
189 
190         // and verify that copy retains these settings
191         ObjectMapper m2 = m.copy();
192         SerializationConfig config2 = m2.getSerializationConfig();
193         assertSame(customIncl, config2.getDefaultPropertyInclusion());
194         assertSame(customSetter, config2.getDefaultSetterInfo());
195         assertEquals(Boolean.TRUE, config2.getDefaultMergeable());
196         assertSame(customVis, config2.getDefaultVisibilityChecker());
197     }
198 
199     // [databind#2785]
testCopyOfSubtypeResolver2785()200     public void testCopyOfSubtypeResolver2785() throws Exception {
201         ObjectMapper objectMapper = new ObjectMapper().copy();
202         objectMapper.registerSubtypes(Impl2785.class);
203         Object result = objectMapper.readValue("{ \"packetType\": \"myType\" }", Base2785.class);
204         assertNotNull(result);
205     }
206 
testFailedCopy()207     public void testFailedCopy() throws Exception
208     {
209         NoCopyMapper src = new NoCopyMapper();
210         try {
211             src.copy();
212             fail("Should not pass");
213         } catch (IllegalStateException e) {
214             verifyException(e, "does not override copy()");
215         }
216     }
217 
testAnnotationIntrospectorCopyin()218     public void testAnnotationIntrospectorCopyin()
219     {
220         ObjectMapper m = new ObjectMapper();
221         m.setAnnotationIntrospector(new MyAnnotationIntrospector());
222         assertEquals(MyAnnotationIntrospector.class,
223                 m.getDeserializationConfig().getAnnotationIntrospector().getClass());
224         ObjectMapper m2 = m.copy();
225 
226         assertEquals(MyAnnotationIntrospector.class,
227                 m2.getDeserializationConfig().getAnnotationIntrospector().getClass());
228         assertEquals(MyAnnotationIntrospector.class,
229                 m2.getSerializationConfig().getAnnotationIntrospector().getClass());
230     }
231 
232     /*
233     /**********************************************************
234     /* Test methods, other
235     /**********************************************************
236      */
237 
testProps()238     public void testProps()
239     {
240         ObjectMapper m = new ObjectMapper();
241         // should have default factory
242         assertNotNull(m.getNodeFactory());
243         JsonNodeFactory nf = new JsonNodeFactory(true);
244         m.setNodeFactory(nf);
245         assertNull(m.getInjectableValues());
246         assertSame(nf, m.getNodeFactory());
247     }
248 
249     // Test to ensure that we can check property ordering defaults...
testConfigForPropertySorting()250     public void testConfigForPropertySorting() throws Exception
251     {
252         ObjectMapper m = new ObjectMapper();
253 
254         // sort-alphabetically is disabled by default:
255         assertFalse(m.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
256         SerializationConfig sc = m.getSerializationConfig();
257         assertFalse(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
258         assertFalse(sc.shouldSortPropertiesAlphabetically());
259         DeserializationConfig dc = m.getDeserializationConfig();
260         assertFalse(dc.shouldSortPropertiesAlphabetically());
261 
262         // but when enabled, should be visible:
263         m = jsonMapperBuilder()
264                 .enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY)
265                 .build();
266         sc = m.getSerializationConfig();
267         assertTrue(sc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
268         assertTrue(sc.shouldSortPropertiesAlphabetically());
269         dc = m.getDeserializationConfig();
270         // and not just via SerializationConfig, but also via DeserializationConfig
271         assertTrue(dc.isEnabled(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY));
272         assertTrue(dc.shouldSortPropertiesAlphabetically());
273     }
274 
testJsonFactoryLinkage()275     public void testJsonFactoryLinkage()
276     {
277         // first, implicit factory, giving implicit linkage
278         assertSame(MAPPER, MAPPER.getFactory().getCodec());
279 
280         // and then explicit factory, which should also be implicitly linked
281         JsonFactory f = new JsonFactory();
282         ObjectMapper m = new ObjectMapper(f);
283         assertSame(f, m.getFactory());
284         assertSame(m, f.getCodec());
285     }
286 
testProviderConfig()287     public void testProviderConfig() throws Exception
288     {
289         ObjectMapper m = new ObjectMapper();
290         final String JSON = "{ \"x\" : 3 }";
291 
292         assertEquals(0, m._deserializationContext._cache.cachedDeserializersCount());
293         // and then should get one constructed for:
294         Bean bean = m.readValue(JSON, Bean.class);
295         assertNotNull(bean);
296         // Since 2.6, serializer for int also cached:
297         assertEquals(2, m._deserializationContext._cache.cachedDeserializersCount());
298         m._deserializationContext._cache.flushCachedDeserializers();
299         assertEquals(0, m._deserializationContext._cache.cachedDeserializersCount());
300 
301         // 07-Nov-2014, tatu: As per [databind#604] verify that Maps also get cached
302         m = new ObjectMapper();
303         List<?> stuff = m.readValue("[ ]", List.class);
304         assertNotNull(stuff);
305         // may look odd, but due to "Untyped" deserializer thing, we actually have
306         // 4 deserializers (int, List<?>, Map<?,?>, Object)
307         assertEquals(4, m._deserializationContext._cache.cachedDeserializersCount());
308     }
309 
310     // For [databind#689]
testCustomDefaultPrettyPrinter()311     public void testCustomDefaultPrettyPrinter() throws Exception
312     {
313         final ObjectMapper m = new ObjectMapper();
314         final int[] input = new int[] { 1, 2 };
315 
316         // without anything else, compact:
317         assertEquals("[1,2]", m.writeValueAsString(input));
318 
319         // or with default, get... defaults:
320         m.enable(SerializationFeature.INDENT_OUTPUT);
321         assertEquals("[ 1, 2 ]", m.writeValueAsString(input));
322         assertEquals("[ 1, 2 ]", m.writerWithDefaultPrettyPrinter().writeValueAsString(input));
323         assertEquals("[ 1, 2 ]", m.writer().withDefaultPrettyPrinter().writeValueAsString(input));
324 
325         // but then with our custom thingy...
326         m.setDefaultPrettyPrinter(new FooPrettyPrinter());
327         assertEquals("[1 , 2]", m.writeValueAsString(input));
328         assertEquals("[1 , 2]", m.writerWithDefaultPrettyPrinter().writeValueAsString(input));
329         assertEquals("[1 , 2]", m.writer().withDefaultPrettyPrinter().writeValueAsString(input));
330 
331         // and yet, can disable too
332         assertEquals("[1,2]", m.writer().without(SerializationFeature.INDENT_OUTPUT)
333                 .writeValueAsString(input));
334     }
335 
336     // For [databind#703], [databind#978]
testNonSerializabilityOfObject()337     public void testNonSerializabilityOfObject()
338     {
339         ObjectMapper m = new ObjectMapper();
340         assertFalse(m.canSerialize(Object.class));
341         // but this used to pass, incorrectly, second time around
342         assertFalse(m.canSerialize(Object.class));
343 
344         // [databind#978]: Different answer if empty Beans ARE allowed
345         m = new ObjectMapper();
346         m.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
347         assertTrue(m.canSerialize(Object.class));
348         assertTrue(MAPPER.writer().without(SerializationFeature.FAIL_ON_EMPTY_BEANS)
349                 .canSerialize(Object.class));
350         assertFalse(MAPPER.writer().with(SerializationFeature.FAIL_ON_EMPTY_BEANS)
351                 .canSerialize(Object.class));
352     }
353 
354     // for [databind#756]
testEmptyBeanSerializability()355     public void testEmptyBeanSerializability()
356     {
357         // with default settings, error
358         assertFalse(MAPPER.writer().with(SerializationFeature.FAIL_ON_EMPTY_BEANS)
359                 .canSerialize(EmptyBean.class));
360         // but with changes
361         assertTrue(MAPPER.writer().without(SerializationFeature.FAIL_ON_EMPTY_BEANS)
362                 .canSerialize(EmptyBean.class));
363     }
364 
365     // for [databind#2749]: just to check there's no NPE; method really not useful
testCanDeserialize()366     public void testCanDeserialize()
367     {
368         assertTrue(MAPPER.canDeserialize(MAPPER.constructType(EmptyBean.class)));
369         assertTrue(MAPPER.canDeserialize(MAPPER.constructType(Object.class)));
370     }
371 
372     // for [databind#898]
testSerializerProviderAccess()373     public void testSerializerProviderAccess() throws Exception
374     {
375         // ensure we have "fresh" instance, just in case
376         ObjectMapper mapper = new ObjectMapper();
377         JsonSerializer<?> ser = mapper.getSerializerProviderInstance()
378                 .findValueSerializer(Bean.class);
379         assertNotNull(ser);
380         assertEquals(Bean.class, ser.handledType());
381     }
382 
383     // for [databind#1074]
testCopyOfParserFeatures()384     public void testCopyOfParserFeatures() throws Exception
385     {
386         // ensure we have "fresh" instance to start with
387         ObjectMapper mapper = new ObjectMapper();
388         assertFalse(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
389         mapper.configure(JsonParser.Feature.IGNORE_UNDEFINED, true);
390         assertTrue(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
391 
392         ObjectMapper copy = mapper.copy();
393         assertTrue(copy.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
394 
395         // also verify there's no back-linkage
396         copy.configure(JsonParser.Feature.IGNORE_UNDEFINED, false);
397         assertFalse(copy.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
398         assertTrue(mapper.isEnabled(JsonParser.Feature.IGNORE_UNDEFINED));
399     }
400 
401     // since 2.8
testDataOutputViaMapper()402     public void testDataOutputViaMapper() throws Exception
403     {
404         ByteArrayOutputStream bytes = new ByteArrayOutputStream();
405         ObjectNode input = MAPPER.createObjectNode();
406         input.put("a", 1);
407         final String exp = "{\"a\":1}";
408         try (DataOutputStream data = new DataOutputStream(bytes)) {
409             MAPPER.writeValue((DataOutput) data, input);
410         }
411         assertEquals(exp, bytes.toString("UTF-8"));
412 
413         // and also via ObjectWriter...
414         bytes.reset();
415         try (DataOutputStream data = new DataOutputStream(bytes)) {
416             MAPPER.writer().writeValue((DataOutput) data, input);
417         }
418         assertEquals(exp, bytes.toString("UTF-8"));
419     }
420 
421     // since 2.8
422     @SuppressWarnings("unchecked")
testDataInputViaMapper()423     public void testDataInputViaMapper() throws Exception
424     {
425         byte[] src = "{\"a\":1}".getBytes("UTF-8");
426         DataInput input = new DataInputStream(new ByteArrayInputStream(src));
427         Map<String,Object> map = (Map<String,Object>) MAPPER.readValue(input, Map.class);
428         assertEquals(Integer.valueOf(1), map.get("a"));
429 
430         input = new DataInputStream(new ByteArrayInputStream(src));
431         // and via ObjectReader
432         map = MAPPER.readerFor(Map.class)
433                 .readValue(input);
434         assertEquals(Integer.valueOf(1), map.get("a"));
435 
436         input = new DataInputStream(new ByteArrayInputStream(src));
437         JsonNode n = MAPPER.readerFor(Map.class)
438                 .readTree(input);
439         assertNotNull(n);
440     }
441 
442     @SuppressWarnings("serial")
testRegisterDependentModules()443     public void testRegisterDependentModules() {
444         ObjectMapper objectMapper = newJsonMapper();
445 
446         final SimpleModule secondModule = new SimpleModule() {
447             @Override
448             public Object getTypeId() {
449                 return "second";
450             }
451         };
452 
453         final SimpleModule thirdModule = new SimpleModule() {
454             @Override
455             public Object getTypeId() {
456                 return "third";
457             }
458         };
459 
460         final SimpleModule firstModule = new SimpleModule() {
461             @Override
462             public Iterable<? extends Module> getDependencies() {
463                 return Arrays.asList(secondModule, thirdModule);
464             }
465 
466             @Override
467             public Object getTypeId() {
468                 return "main";
469             }
470         };
471 
472         objectMapper.registerModule(firstModule);
473 
474         assertEquals(
475             new HashSet<>(Arrays.asList("second", "third", "main")),
476             objectMapper.getRegisteredModuleIds()
477         );
478     }
479 }
480