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