1 package com.fasterxml.jackson.databind; 2 3 import java.io.IOException; 4 import java.text.DateFormat; 5 import java.util.Date; 6 import java.util.Locale; 7 import java.util.TimeZone; 8 9 import com.fasterxml.jackson.annotation.JsonFormat; 10 import com.fasterxml.jackson.annotation.JsonInclude; 11 import com.fasterxml.jackson.annotation.ObjectIdGenerator; 12 import com.fasterxml.jackson.core.JsonGenerator; 13 import com.fasterxml.jackson.databind.cfg.ContextAttributes; 14 import com.fasterxml.jackson.databind.deser.ContextualDeserializer; 15 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException; 16 import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; 17 import com.fasterxml.jackson.databind.introspect.Annotated; 18 import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition; 19 import com.fasterxml.jackson.databind.jsontype.TypeSerializer; 20 import com.fasterxml.jackson.databind.ser.*; 21 import com.fasterxml.jackson.databind.ser.impl.FailingSerializer; 22 import com.fasterxml.jackson.databind.ser.impl.ReadOnlyClassToSerializerMap; 23 import com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer; 24 import com.fasterxml.jackson.databind.ser.impl.UnknownSerializer; 25 import com.fasterxml.jackson.databind.ser.impl.WritableObjectId; 26 import com.fasterxml.jackson.databind.ser.std.NullSerializer; 27 import com.fasterxml.jackson.databind.type.TypeFactory; 28 import com.fasterxml.jackson.databind.util.ClassUtil; 29 30 /** 31 * Class that defines API used by {@link ObjectMapper} and 32 * {@link JsonSerializer}s to obtain serializers capable of serializing 33 * instances of specific types; as well as the default implementation 34 * of the functionality. 35 *<p> 36 * Provider handles caching aspects of serializer handling; all construction 37 * details are delegated to {@link SerializerFactory} instance. 38 *<p> 39 * Object life-cycle is such that an initial instance ("blueprint") is created 40 * and referenced by {@link ObjectMapper} and {@link ObjectWriter} intances; 41 * but for actual usage, a configured instance is created by using 42 * a create method in sub-class 43 * {@link com.fasterxml.jackson.databind.ser.DefaultSerializerProvider}. 44 * Only this instance can be used for actual serialization calls; blueprint 45 * object is only to be used for creating instances. 46 */ 47 public abstract class SerializerProvider 48 extends DatabindContext 49 { 50 /** 51 * Setting for determining whether mappings for "unknown classes" should be 52 * cached for faster resolution. Usually this isn't needed, but maybe it 53 * is in some cases? 54 */ 55 protected final static boolean CACHE_UNKNOWN_MAPPINGS = false; 56 57 public final static JsonSerializer<Object> DEFAULT_NULL_KEY_SERIALIZER = 58 new FailingSerializer("Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)"); 59 60 /** 61 * Placeholder serializer used when <code>java.lang.Object</code> typed property 62 * is marked to be serialized. 63 *<br> 64 * NOTE: starting with 2.6, this instance is NOT used for any other types, and 65 * separate instances are constructed for "empty" Beans. 66 *<p> 67 * NOTE: changed to <code>protected</code> for 2.3; no need to be publicly available. 68 */ 69 protected final static JsonSerializer<Object> DEFAULT_UNKNOWN_SERIALIZER = new UnknownSerializer(); 70 71 /* 72 /********************************************************** 73 /* Configuration, general 74 /********************************************************** 75 */ 76 77 /** 78 * Serialization configuration to use for serialization processing. 79 */ 80 final protected SerializationConfig _config; 81 82 /** 83 * View used for currently active serialization, if any. 84 * Only set for non-blueprint instances. 85 */ 86 final protected Class<?> _serializationView; 87 88 /* 89 /********************************************************** 90 /* Configuration, factories 91 /********************************************************** 92 */ 93 94 /** 95 * Factory used for constructing actual serializer instances. 96 * Only set for non-blueprint instances. 97 */ 98 final protected SerializerFactory _serializerFactory; 99 100 /* 101 /********************************************************** 102 /* Helper objects for caching, reuse 103 /********************************************************** 104 */ 105 106 /** 107 * Cache for doing type-to-value-serializer lookups. 108 */ 109 final protected SerializerCache _serializerCache; 110 111 /** 112 * Lazily-constructed holder for per-call attributes. 113 * Only set for non-blueprint instances. 114 * 115 * @since 2.3 116 */ 117 protected transient ContextAttributes _attributes; 118 119 /* 120 /********************************************************** 121 /* Configuration, specialized serializers 122 /********************************************************** 123 */ 124 125 /** 126 * Serializer that gets called for values of types for which no 127 * serializers can be constructed. 128 *<p> 129 * The default serializer will simply thrown an exception. 130 */ 131 protected JsonSerializer<Object> _unknownTypeSerializer = DEFAULT_UNKNOWN_SERIALIZER; 132 133 /** 134 * Serializer used to output non-null keys of Maps (which will get 135 * output as JSON Objects), if not null; if null, us the standard 136 * default key serializer. 137 */ 138 protected JsonSerializer<Object> _keySerializer; 139 140 /** 141 * Serializer used to output a null value. Default implementation 142 * writes nulls using {@link JsonGenerator#writeNull}. 143 */ 144 protected JsonSerializer<Object> _nullValueSerializer = NullSerializer.instance; 145 146 /** 147 * Serializer used to (try to) output a null key, due to an entry of 148 * {@link java.util.Map} having null key. 149 * The default implementation will throw an exception if this happens; 150 * alternative implementation (like one that would write an Empty String) 151 * can be defined. 152 */ 153 protected JsonSerializer<Object> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER; 154 155 /* 156 /********************************************************** 157 /* State, for non-blueprint instances: generic 158 /********************************************************** 159 */ 160 161 /** 162 * For fast lookups, we will have a local non-shared read-only 163 * map that contains serializers previously fetched. 164 */ 165 protected final ReadOnlyClassToSerializerMap _knownSerializers; 166 167 /** 168 * Lazily acquired and instantiated formatter object: initialized 169 * first time it is needed, reused afterwards. Used via instances 170 * (not blueprints), so that access need not be thread-safe. 171 */ 172 protected DateFormat _dateFormat; 173 174 /** 175 * Flag set to indicate that we are using vanilla null value serialization 176 * 177 * @since 2.3 178 */ 179 protected final boolean _stdNullValueSerializer; 180 181 /* 182 /********************************************************** 183 /* Life-cycle 184 /********************************************************** 185 */ 186 187 /** 188 * Constructor for creating master (or "blue-print") provider object, 189 * which is only used as the template for constructing per-binding 190 * instances. 191 */ SerializerProvider()192 public SerializerProvider() 193 { 194 _config = null; 195 _serializerFactory = null; 196 _serializerCache = new SerializerCache(); 197 // Blueprints doesn't have access to any serializers... 198 _knownSerializers = null; 199 200 _serializationView = null; 201 _attributes = null; 202 203 // not relevant for blueprint instance, could set either way: 204 _stdNullValueSerializer = true; 205 } 206 207 /** 208 * "Copy-constructor", used by sub-classes when creating actual non-blueprint 209 * instances to use. 210 * 211 * @param src Blueprint object used as the baseline for this instance 212 */ SerializerProvider(SerializerProvider src, SerializationConfig config, SerializerFactory f)213 protected SerializerProvider(SerializerProvider src, 214 SerializationConfig config, SerializerFactory f) 215 { 216 _serializerFactory = f; 217 _config = config; 218 219 _serializerCache = src._serializerCache; 220 _unknownTypeSerializer = src._unknownTypeSerializer; 221 _keySerializer = src._keySerializer; 222 _nullValueSerializer = src._nullValueSerializer; 223 _nullKeySerializer = src._nullKeySerializer; 224 225 _stdNullValueSerializer = (_nullValueSerializer == DEFAULT_NULL_KEY_SERIALIZER); 226 227 _serializationView = config.getActiveView(); 228 _attributes = config.getAttributes(); 229 230 /* Non-blueprint instances do have a read-only map; one that doesn't 231 * need synchronization for lookups. 232 */ 233 _knownSerializers = _serializerCache.getReadOnlyLookupMap(); 234 } 235 236 /** 237 * Copy-constructor used when making a copy of a blueprint instance. 238 * 239 * @since 2.5 240 */ SerializerProvider(SerializerProvider src)241 protected SerializerProvider(SerializerProvider src) 242 { 243 // since this is assumed to be a blue-print instance, many settings missing: 244 _config = null; 245 _serializationView = null; 246 _serializerFactory = null; 247 _knownSerializers = null; 248 249 // and others initialized to default empty state 250 _serializerCache = new SerializerCache(); 251 252 _unknownTypeSerializer = src._unknownTypeSerializer; 253 _keySerializer = src._keySerializer; 254 _nullValueSerializer = src._nullValueSerializer; 255 _nullKeySerializer = src._nullKeySerializer; 256 257 _stdNullValueSerializer = src._stdNullValueSerializer; 258 } 259 260 /* 261 /********************************************************** 262 /* Methods for configuring default settings 263 /********************************************************** 264 */ 265 266 /** 267 * Method that can be used to specify serializer that will be 268 * used to write JSON property names matching null keys for Java 269 * Maps (which will throw an exception if try write such property 270 * name) 271 */ setDefaultKeySerializer(JsonSerializer<Object> ks)272 public void setDefaultKeySerializer(JsonSerializer<Object> ks) 273 { 274 if (ks == null) { 275 throw new IllegalArgumentException("Cannot pass null JsonSerializer"); 276 } 277 _keySerializer = ks; 278 } 279 280 /** 281 * Method that can be used to specify serializer that will be 282 * used to write JSON values matching Java null values 283 * instead of default one (which simply writes JSON null). 284 *<p> 285 * Note that you can get finer control over serializer to use by overriding 286 * {@link #findNullValueSerializer}, which gets called once per each 287 * property. 288 */ setNullValueSerializer(JsonSerializer<Object> nvs)289 public void setNullValueSerializer(JsonSerializer<Object> nvs) 290 { 291 if (nvs == null) { 292 throw new IllegalArgumentException("Cannot pass null JsonSerializer"); 293 } 294 _nullValueSerializer = nvs; 295 } 296 297 /** 298 * Method that can be used to specify serializer to use for serializing 299 * all non-null JSON property names, unless more specific key serializer 300 * is found (i.e. if not custom key serializer has been registered for 301 * Java type). 302 *<p> 303 * Note that key serializer registration are different from value serializer 304 * registrations. 305 */ setNullKeySerializer(JsonSerializer<Object> nks)306 public void setNullKeySerializer(JsonSerializer<Object> nks) 307 { 308 if (nks == null) { 309 throw new IllegalArgumentException("Cannot pass null JsonSerializer"); 310 } 311 _nullKeySerializer = nks; 312 } 313 314 /* 315 /********************************************************** 316 /* DatabindContext implementation (and closely related but ser-specific) 317 /********************************************************** 318 */ 319 320 /** 321 * Method for accessing configuration for the serialization processing. 322 */ 323 @Override getConfig()324 public final SerializationConfig getConfig() { return _config; } 325 326 @Override getAnnotationIntrospector()327 public final AnnotationIntrospector getAnnotationIntrospector() { 328 return _config.getAnnotationIntrospector(); 329 } 330 331 @Override getTypeFactory()332 public final TypeFactory getTypeFactory() { 333 return _config.getTypeFactory(); 334 } 335 336 @Override // since 2.11 constructSpecializedType(JavaType baseType, Class<?> subclass)337 public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) 338 throws IllegalArgumentException 339 { 340 if (baseType.hasRawClass(subclass)) { 341 return baseType; 342 } 343 // Need little bit different handling due to [databind#2632]; pass `true` for 344 // "relaxed" type assingment checks. 345 return getConfig().getTypeFactory().constructSpecializedType(baseType, subclass, true); 346 } 347 348 @Override getActiveView()349 public final Class<?> getActiveView() { return _serializationView; } 350 351 /** 352 * @deprecated Since 2.2, use {@link #getActiveView} instead. 353 */ 354 @Deprecated getSerializationView()355 public final Class<?> getSerializationView() { return _serializationView; } 356 357 @Override canOverrideAccessModifiers()358 public final boolean canOverrideAccessModifiers() { 359 return _config.canOverrideAccessModifiers(); 360 } 361 362 @Override isEnabled(MapperFeature feature)363 public final boolean isEnabled(MapperFeature feature) { 364 return _config.isEnabled(feature); 365 } 366 367 @Override getDefaultPropertyFormat(Class<?> baseType)368 public final JsonFormat.Value getDefaultPropertyFormat(Class<?> baseType) { 369 return _config.getDefaultPropertyFormat(baseType); 370 } 371 372 /** 373 * @since 2.8 374 */ getDefaultPropertyInclusion(Class<?> baseType)375 public final JsonInclude.Value getDefaultPropertyInclusion(Class<?> baseType) { 376 return _config.getDefaultPropertyInclusion(baseType); 377 } 378 379 /** 380 * Method for accessing default Locale to use: convenience method for 381 *<pre> 382 * getConfig().getLocale(); 383 *</pre> 384 */ 385 @Override getLocale()386 public Locale getLocale() { 387 return _config.getLocale(); 388 } 389 390 /** 391 * Method for accessing default TimeZone to use: convenience method for 392 *<pre> 393 * getConfig().getTimeZone(); 394 *</pre> 395 */ 396 @Override getTimeZone()397 public TimeZone getTimeZone() { 398 return _config.getTimeZone(); 399 } 400 401 /* 402 /********************************************************** 403 /* Generic attributes (2.3+) 404 /********************************************************** 405 */ 406 407 @Override getAttribute(Object key)408 public Object getAttribute(Object key) { 409 return _attributes.getAttribute(key); 410 } 411 412 @Override setAttribute(Object key, Object value)413 public SerializerProvider setAttribute(Object key, Object value) 414 { 415 _attributes = _attributes.withPerCallAttribute(key, value); 416 return this; 417 } 418 419 /* 420 /********************************************************** 421 /* Access to general configuration 422 /********************************************************** 423 */ 424 425 /** 426 * Convenience method for checking whether specified serialization 427 * feature is enabled or not. 428 * Shortcut for: 429 *<pre> 430 * getConfig().isEnabled(feature); 431 *</pre> 432 */ isEnabled(SerializationFeature feature)433 public final boolean isEnabled(SerializationFeature feature) { 434 return _config.isEnabled(feature); 435 } 436 437 /** 438 * "Bulk" access method for checking that all features specified by 439 * mask are enabled. 440 * 441 * @since 2.3 442 */ hasSerializationFeatures(int featureMask)443 public final boolean hasSerializationFeatures(int featureMask) { 444 return _config.hasSerializationFeatures(featureMask); 445 } 446 447 /** 448 * Convenience method for accessing provider to find serialization filters used, 449 * equivalent to calling: 450 *<pre> 451 * getConfig().getFilterProvider(); 452 *</pre> 453 */ getFilterProvider()454 public final FilterProvider getFilterProvider() { 455 return _config.getFilterProvider(); 456 } 457 458 /** 459 *<p> 460 * NOTE: current implementation simply returns `null` as generator is not yet 461 * assigned to this provider. 462 * 463 * @since 2.8 464 */ getGenerator()465 public JsonGenerator getGenerator() { 466 return null; 467 } 468 469 /* 470 /********************************************************** 471 /* Access to Object Id aspects 472 /********************************************************** 473 */ 474 475 /** 476 * Method called to find the Object Id for given POJO, if one 477 * has been generated. Will always return a non-null Object; 478 * contents vary depending on whether an Object Id already 479 * exists or not. 480 */ findObjectId(Object forPojo, ObjectIdGenerator<?> generatorType)481 public abstract WritableObjectId findObjectId(Object forPojo, 482 ObjectIdGenerator<?> generatorType); 483 484 /* 485 /********************************************************** 486 /* General serializer locating functionality 487 /********************************************************** 488 */ 489 490 /** 491 * Method called to get hold of a serializer for a value of given type; 492 * or if no such serializer can be found, a default handler (which 493 * may do a best-effort generic serialization or just simply 494 * throw an exception when invoked). 495 *<p> 496 * Note: this method is only called for non-null values; not for keys 497 * or null values. For these, check out other accessor methods. 498 *<p> 499 * Note that serializers produced should NOT handle polymorphic serialization 500 * aspects; separate {@link TypeSerializer} is to be constructed by caller 501 * if and as necessary. 502 * 503 * @throws JsonMappingException if there are fatal problems with 504 * accessing suitable serializer; including that of not 505 * finding any serializer 506 */ 507 @SuppressWarnings("unchecked") findValueSerializer(Class<?> valueType, BeanProperty property)508 public JsonSerializer<Object> findValueSerializer(Class<?> valueType, BeanProperty property) 509 throws JsonMappingException 510 { 511 // Fast lookup from local lookup thingy works? 512 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 513 if (ser == null) { 514 // If not, maybe shared map already has it? 515 ser = _serializerCache.untypedValueSerializer(valueType); 516 if (ser == null) { 517 // ... possibly as fully typed? 518 ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); 519 if (ser == null) { 520 // If neither, must create 521 ser = _createAndCacheUntypedSerializer(valueType); 522 // Not found? Must use the unknown type serializer, which will report error later on 523 if (ser == null) { 524 ser = getUnknownTypeSerializer(valueType); 525 // Should this be added to lookups? 526 if (CACHE_UNKNOWN_MAPPINGS) { 527 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 528 } 529 return ser; 530 } 531 } 532 } 533 } 534 // at this point, resolution has occured, but not contextualization 535 return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property); 536 } 537 538 /** 539 * Similar to {@link #findValueSerializer(Class,BeanProperty)}, but takes 540 * full generics-aware type instead of raw class. 541 * This is necessary for accurate handling of external type information, 542 * to handle polymorphic types. 543 *<p> 544 * Note: this call will also contextualize serializer before returning it. 545 * 546 * @param property When creating secondary serializers, property for which 547 * serializer is needed: annotations of the property (or bean that contains it) 548 * may be checked to create contextual serializers. 549 */ 550 @SuppressWarnings("unchecked") findValueSerializer(JavaType valueType, BeanProperty property)551 public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property) 552 throws JsonMappingException 553 { 554 if (valueType == null) { 555 reportMappingProblem("Null passed for `valueType` of `findValueSerializer()`"); 556 } 557 // (see comments from above method) 558 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 559 if (ser == null) { 560 ser = _serializerCache.untypedValueSerializer(valueType); 561 if (ser == null) { 562 ser = _createAndCacheUntypedSerializer(valueType); 563 if (ser == null) { 564 ser = getUnknownTypeSerializer(valueType.getRawClass()); 565 if (CACHE_UNKNOWN_MAPPINGS) { 566 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 567 } 568 return ser; 569 } 570 } 571 } 572 return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property); 573 } 574 575 /** 576 * Method variant used when we do NOT want contextualization to happen; it will need 577 * to be handled at a later point, but caller wants to be able to do that 578 * as needed; sometimes to avoid infinite loops 579 * 580 * @since 2.5 581 */ findValueSerializer(Class<?> valueType)582 public JsonSerializer<Object> findValueSerializer(Class<?> valueType) throws JsonMappingException 583 { 584 // (see comments from above method) 585 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 586 if (ser == null) { 587 ser = _serializerCache.untypedValueSerializer(valueType); 588 if (ser == null) { 589 ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); 590 if (ser == null) { 591 ser = _createAndCacheUntypedSerializer(valueType); 592 if (ser == null) { 593 ser = getUnknownTypeSerializer(valueType); 594 if (CACHE_UNKNOWN_MAPPINGS) { 595 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 596 } 597 } 598 } 599 } 600 } 601 return ser; 602 } 603 604 /** 605 * Method variant used when we do NOT want contextualization to happen; it will need 606 * to be handled at a later point, but caller wants to be able to do that 607 * as needed; sometimes to avoid infinite loops 608 * 609 * @since 2.5 610 */ findValueSerializer(JavaType valueType)611 public JsonSerializer<Object> findValueSerializer(JavaType valueType) 612 throws JsonMappingException 613 { 614 // (see comments from above method) 615 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 616 if (ser == null) { 617 ser = _serializerCache.untypedValueSerializer(valueType); 618 if (ser == null) { 619 ser = _createAndCacheUntypedSerializer(valueType); 620 if (ser == null) { 621 ser = getUnknownTypeSerializer(valueType.getRawClass()); 622 if (CACHE_UNKNOWN_MAPPINGS) { 623 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 624 } 625 } 626 } 627 } 628 return ser; 629 } 630 631 /** 632 * Similar to {@link #findValueSerializer(JavaType, BeanProperty)}, but used 633 * when finding "primary" property value serializer (one directly handling 634 * value of the property). Difference has to do with contextual resolution, 635 * and method(s) called: this method should only be called when caller is 636 * certain that this is the primary property value serializer. 637 * 638 * @param valueType Type of values to serialize 639 * @param property Property that is being handled; will never be null, and its 640 * type has to match <code>valueType</code> parameter. 641 * 642 * @since 2.3 643 */ 644 @SuppressWarnings("unchecked") findPrimaryPropertySerializer(JavaType valueType, BeanProperty property)645 public JsonSerializer<Object> findPrimaryPropertySerializer(JavaType valueType, BeanProperty property) 646 throws JsonMappingException 647 { 648 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 649 if (ser == null) { 650 ser = _serializerCache.untypedValueSerializer(valueType); 651 if (ser == null) { 652 ser = _createAndCacheUntypedSerializer(valueType); 653 if (ser == null) { 654 ser = getUnknownTypeSerializer(valueType.getRawClass()); 655 // Should this be added to lookups? 656 if (CACHE_UNKNOWN_MAPPINGS) { 657 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 658 } 659 return ser; 660 } 661 } 662 } 663 return (JsonSerializer<Object>) handlePrimaryContextualization(ser, property); 664 } 665 666 /** 667 * See {@link #findPrimaryPropertySerializer(JavaType, BeanProperty)} 668 * 669 * @since 2.3 670 */ 671 @SuppressWarnings("unchecked") findPrimaryPropertySerializer(Class<?> valueType, BeanProperty property)672 public JsonSerializer<Object> findPrimaryPropertySerializer(Class<?> valueType, 673 BeanProperty property) 674 throws JsonMappingException 675 { 676 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 677 if (ser == null) { 678 ser = _serializerCache.untypedValueSerializer(valueType); 679 if (ser == null) { 680 ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); 681 if (ser == null) { 682 ser = _createAndCacheUntypedSerializer(valueType); 683 if (ser == null) { 684 ser = getUnknownTypeSerializer(valueType); 685 if (CACHE_UNKNOWN_MAPPINGS) { 686 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 687 } 688 return ser; 689 } 690 } 691 } 692 } 693 return (JsonSerializer<Object>) handlePrimaryContextualization(ser, property); 694 } 695 696 /** 697 * Alternative to {@link #findPrimaryPropertySerializer(JavaType, BeanProperty)} called not 698 * for primary value, but "content" of such primary serializer: element of an array or 699 * {@link java.util.Collection}, value of {@link java.util.Map} entry and so on. 700 * This means that {@code property} passed (if any) does NOT represent value for which 701 * serializer is requested but its secondary type (or secondary type of that type, 702 * recursively). 703 *<p> 704 * Serializer returned SHOULD NOT handle type information; caller will (have to) add 705 * suitable wrapping if necessary. 706 *<p> 707 * Note: this call will also contextualize serializer (call {@code createContextual()} 708 * before returning it, if applicable (implements {@code ContextualSerializer}) 709 * 710 * @param valueType Type of values to serialize 711 * @param property Property that indirectly refers to value being serialized (optional, 712 * may be {@code null} for root level serializers) 713 * 714 * @since 2.11 715 */ 716 @SuppressWarnings("unchecked") findContentValueSerializer(JavaType valueType, BeanProperty property)717 public JsonSerializer<Object> findContentValueSerializer(JavaType valueType, BeanProperty property) 718 throws JsonMappingException 719 { 720 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 721 if (ser == null) { 722 ser = _serializerCache.untypedValueSerializer(valueType); 723 if (ser == null) { 724 ser = _createAndCacheUntypedSerializer(valueType); 725 if (ser == null) { 726 ser = getUnknownTypeSerializer(valueType.getRawClass()); 727 // Should this be added to lookups? 728 if (CACHE_UNKNOWN_MAPPINGS) { 729 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 730 } 731 return ser; 732 } 733 } 734 } 735 return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property); 736 } 737 738 /** 739 * See {@link #findContentValueSerializer(JavaType, BeanProperty)}. 740 * 741 * @since 2.11 742 */ 743 @SuppressWarnings("unchecked") findContentValueSerializer(Class<?> valueType, BeanProperty property)744 public JsonSerializer<Object> findContentValueSerializer(Class<?> valueType, 745 BeanProperty property) 746 throws JsonMappingException 747 { 748 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); 749 if (ser == null) { 750 ser = _serializerCache.untypedValueSerializer(valueType); 751 if (ser == null) { 752 ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); 753 if (ser == null) { 754 ser = _createAndCacheUntypedSerializer(valueType); 755 if (ser == null) { 756 ser = getUnknownTypeSerializer(valueType); 757 if (CACHE_UNKNOWN_MAPPINGS) { 758 _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); 759 } 760 return ser; 761 } 762 } 763 } 764 } 765 return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property); 766 } 767 768 /** 769 * Method called to locate regular serializer, matching type serializer, 770 * and if both found, wrap them in a serializer that calls both in correct 771 * sequence. This method is currently only used for root-level serializer 772 * handling to allow for simpler caching. A call can always be replaced 773 * by equivalent calls to access serializer and type serializer separately. 774 * 775 * @param valueType Type for purpose of locating a serializer; usually dynamic 776 * runtime type, but can also be static declared type, depending on configuration 777 * @param cache Whether resulting value serializer should be cached or not; this is just 778 * a hint 779 * @param property When creating secondary serializers, property for which 780 * serializer is needed: annotations of the property (or bean that contains it) 781 * may be checked to create contextual serializers. 782 */ findTypedValueSerializer(Class<?> valueType, boolean cache, BeanProperty property)783 public JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType, 784 boolean cache, BeanProperty property) 785 throws JsonMappingException 786 { 787 // Two-phase lookups; local non-shared cache, then shared: 788 JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType); 789 if (ser != null) { 790 return ser; 791 } 792 // If not, maybe shared map already has it? 793 ser = _serializerCache.typedValueSerializer(valueType); 794 if (ser != null) { 795 return ser; 796 } 797 798 // Well, let's just compose from pieces: 799 ser = findValueSerializer(valueType, property); 800 TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, 801 _config.constructType(valueType)); 802 if (typeSer != null) { 803 typeSer = typeSer.forProperty(property); 804 ser = new TypeWrappedSerializer(typeSer, ser); 805 } 806 if (cache) { 807 _serializerCache.addTypedSerializer(valueType, ser); 808 } 809 return ser; 810 } 811 812 /** 813 * Method called to locate regular serializer, matching type serializer, 814 * and if both found, wrap them in a serializer that calls both in correct 815 * sequence. This method is currently only used for root-level serializer 816 * handling to allow for simpler caching. A call can always be replaced 817 * by equivalent calls to access serializer and type serializer separately. 818 * 819 * @param valueType Declared type of value being serialized (which may not 820 * be actual runtime type); used for finding both value serializer and 821 * type serializer to use for adding polymorphic type (if any) 822 * @param cache Whether resulting value serializer should be cached or not; this is just 823 * a hint 824 * @param property When creating secondary serializers, property for which 825 * serializer is needed: annotations of the property (or bean that contains it) 826 * may be checked to create contextual serializers. 827 */ findTypedValueSerializer(JavaType valueType, boolean cache, BeanProperty property)828 public JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, boolean cache, 829 BeanProperty property) 830 throws JsonMappingException 831 { 832 // Two-phase lookups; local non-shared cache, then shared: 833 JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType); 834 if (ser != null) { 835 return ser; 836 } 837 // If not, maybe shared map already has it? 838 ser = _serializerCache.typedValueSerializer(valueType); 839 if (ser != null) { 840 return ser; 841 } 842 843 // Well, let's just compose from pieces: 844 ser = findValueSerializer(valueType, property); 845 TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType); 846 if (typeSer != null) { 847 typeSer = typeSer.forProperty(property); 848 ser = new TypeWrappedSerializer(typeSer, ser); 849 } 850 if (cache) { 851 _serializerCache.addTypedSerializer(valueType, ser); 852 } 853 return ser; 854 } 855 856 /** 857 * Method called to get the {@link TypeSerializer} to use for including Type Id necessary 858 * for serializing for the given Java class. 859 * Useful for schema generators. 860 * 861 * @since 2.6 862 */ findTypeSerializer(JavaType javaType)863 public TypeSerializer findTypeSerializer(JavaType javaType) throws JsonMappingException { 864 return _serializerFactory.createTypeSerializer(_config, javaType); 865 } 866 867 /** 868 * Method called to get the serializer to use for serializing 869 * non-null Map keys. Separation from regular 870 * {@link #findValueSerializer} method is because actual write 871 * method must be different (@link JsonGenerator#writeFieldName}; 872 * but also since behavior for some key types may differ. 873 *<p> 874 * Note that the serializer itself can be called with instances 875 * of any Java object, but not nulls. 876 */ findKeySerializer(JavaType keyType, BeanProperty property)877 public JsonSerializer<Object> findKeySerializer(JavaType keyType, BeanProperty property) 878 throws JsonMappingException 879 { 880 JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(this, keyType, _keySerializer); 881 // 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too 882 return _handleContextualResolvable(ser, property); 883 } 884 885 /** 886 * @since 2.7 887 */ findKeySerializer(Class<?> rawKeyType, BeanProperty property)888 public JsonSerializer<Object> findKeySerializer(Class<?> rawKeyType, BeanProperty property) 889 throws JsonMappingException 890 { 891 return findKeySerializer(_config.constructType(rawKeyType), property); 892 } 893 894 /* 895 /******************************************************** 896 /* Accessors for specialized serializers 897 /******************************************************** 898 */ 899 900 /** 901 * @since 2.0 902 */ getDefaultNullKeySerializer()903 public JsonSerializer<Object> getDefaultNullKeySerializer() { 904 return _nullKeySerializer; 905 } 906 907 /** 908 * @since 2.0 909 */ getDefaultNullValueSerializer()910 public JsonSerializer<Object> getDefaultNullValueSerializer() { 911 return _nullValueSerializer; 912 } 913 914 /** 915 * Method called to get the serializer to use for serializing 916 * Map keys that are nulls: this is needed since JSON does not allow 917 * any non-String value as key, including null. 918 *<p> 919 * Typically, returned serializer 920 * will either throw an exception, or use an empty String; but 921 * other behaviors are possible. 922 */ 923 /** 924 * Method called to find a serializer to use for null values for given 925 * declared type. Note that type is completely based on declared type, 926 * since nulls in Java have no type and thus runtime type cannot be 927 * determined. 928 * 929 * @since 2.0 930 */ findNullKeySerializer(JavaType serializationType, BeanProperty property)931 public JsonSerializer<Object> findNullKeySerializer(JavaType serializationType, 932 BeanProperty property) 933 throws JsonMappingException 934 { 935 return _nullKeySerializer; 936 } 937 938 /** 939 * Method called to get the serializer to use for serializing null 940 * values for specified property. 941 *<p> 942 * Default implementation simply calls {@link #getDefaultNullValueSerializer()}; 943 * can be overridden to add custom null serialization for properties 944 * of certain type or name. This gives method full granularity to basically 945 * override null handling for any specific property or class of properties. 946 * 947 * @since 2.0 948 */ findNullValueSerializer(BeanProperty property)949 public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) 950 throws JsonMappingException { 951 return _nullValueSerializer; 952 } 953 954 /** 955 * Method called to get the serializer to use if provider 956 * cannot determine an actual type-specific serializer 957 * to use; typically when none of {@link SerializerFactory} 958 * instances are able to construct a serializer. 959 *<p> 960 * Typically, returned serializer will throw an exception, 961 * although alternatively {@link com.fasterxml.jackson.databind.ser.std.ToStringSerializer} 962 * could be returned as well. 963 * 964 * @param unknownType Type for which no serializer is found 965 */ getUnknownTypeSerializer(Class<?> unknownType)966 public JsonSerializer<Object> getUnknownTypeSerializer(Class<?> unknownType) { 967 // 23-Apr-2015, tatu: Only return shared instance if nominal type is Object.class 968 if (unknownType == Object.class) { 969 return _unknownTypeSerializer; 970 } 971 // otherwise construct explicit instance with property handled type 972 return new UnknownSerializer(unknownType); 973 } 974 975 /** 976 * Helper method called to see if given serializer is considered to be 977 * something returned by {@link #getUnknownTypeSerializer}, that is, something 978 * for which no regular serializer was found or constructed. 979 * 980 * @since 2.5 981 */ isUnknownTypeSerializer(JsonSerializer<?> ser)982 public boolean isUnknownTypeSerializer(JsonSerializer<?> ser) { 983 if ((ser == _unknownTypeSerializer) || (ser == null)) { 984 return true; 985 } 986 // 23-Apr-2015, tatu: "empty" serializer is trickier; needs to consider 987 // error handling 988 if (isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS)) { 989 if (ser.getClass() == UnknownSerializer.class) { 990 return true; 991 } 992 } 993 return false; 994 } 995 996 /* 997 /********************************************************** 998 /* Methods for creating instances based on annotations 999 /********************************************************** 1000 */ 1001 1002 /** 1003 * Method that can be called to construct and configure serializer instance, 1004 * either given a {@link Class} to instantiate (with default constructor), 1005 * or an uninitialized serializer instance. 1006 * Either way, serialize will be properly resolved 1007 * (via {@link com.fasterxml.jackson.databind.ser.ResolvableSerializer}) and/or contextualized 1008 * (via {@link com.fasterxml.jackson.databind.ser.ContextualSerializer}) as necessary. 1009 * 1010 * @param annotated Annotated entity that contained definition 1011 * @param serDef Serializer definition: either an instance or class 1012 */ serializerInstance(Annotated annotated, Object serDef)1013 public abstract JsonSerializer<Object> serializerInstance(Annotated annotated, 1014 Object serDef) 1015 throws JsonMappingException; 1016 1017 /** 1018 * Method that can be called to construct and configure {@link JsonInclude} 1019 * filter instance, 1020 * given a {@link Class} to instantiate (with default constructor, by default). 1021 * 1022 * @param forProperty (optional) If filter is created for a property, that property; 1023 * `null` if filter created via defaulting, global or per-type. 1024 * 1025 * @since 2.9 1026 */ includeFilterInstance(BeanPropertyDefinition forProperty, Class<?> filterClass)1027 public abstract Object includeFilterInstance(BeanPropertyDefinition forProperty, 1028 Class<?> filterClass) 1029 throws JsonMappingException; 1030 1031 /** 1032 * Follow-up method that may be called after calling {@link #includeFilterInstance}, 1033 * to check handling of `null` values by the filter. 1034 * 1035 * @since 2.9 1036 */ includeFilterSuppressNulls(Object filter)1037 public abstract boolean includeFilterSuppressNulls(Object filter) 1038 throws JsonMappingException; 1039 1040 /* 1041 /********************************************************** 1042 /* Support for contextualization 1043 /********************************************************** 1044 */ 1045 1046 /** 1047 * Method called for primary property serializers (ones 1048 * directly created to serialize values of a POJO property), 1049 * to handle details of resolving 1050 * {@link ContextualSerializer} with given property context. 1051 * 1052 * @param property Property for which the given primary serializer is used; never null. 1053 * 1054 * @since 2.3 1055 */ handlePrimaryContextualization(JsonSerializer<?> ser, BeanProperty property)1056 public JsonSerializer<?> handlePrimaryContextualization(JsonSerializer<?> ser, 1057 BeanProperty property) 1058 throws JsonMappingException 1059 { 1060 if (ser != null) { 1061 if (ser instanceof ContextualSerializer) { 1062 ser = ((ContextualSerializer) ser).createContextual(this, property); 1063 } 1064 } 1065 return ser; 1066 } 1067 1068 /** 1069 * Method called for secondary property serializers (ones 1070 * NOT directly created to serialize values of a POJO property 1071 * but instead created as a dependant serializer -- such as value serializers 1072 * for structured types, or serializers for root values) 1073 * to handle details of resolving 1074 * {@link ContextualDeserializer} with given property context. 1075 * Given that these serializers are not directly related to given property 1076 * (or, in case of root value property, to any property), annotations 1077 * accessible may or may not be relevant. 1078 * 1079 * @param property Property for which serializer is used, if any; null 1080 * when deserializing root values 1081 * 1082 * @since 2.3 1083 */ handleSecondaryContextualization(JsonSerializer<?> ser, BeanProperty property)1084 public JsonSerializer<?> handleSecondaryContextualization(JsonSerializer<?> ser, 1085 BeanProperty property) 1086 throws JsonMappingException 1087 { 1088 if (ser != null) { 1089 if (ser instanceof ContextualSerializer) { 1090 ser = ((ContextualSerializer) ser).createContextual(this, property); 1091 } 1092 } 1093 return ser; 1094 } 1095 1096 /* 1097 /******************************************************** 1098 /* Convenience methods for serializing using default methods 1099 /******************************************************** 1100 */ 1101 1102 /** 1103 * Convenience method that will serialize given value (which can be 1104 * null) using standard serializer locating functionality. It can 1105 * be called for all values including field and Map values, but usually 1106 * field values are best handled calling 1107 * {@link #defaultSerializeField} instead. 1108 */ defaultSerializeValue(Object value, JsonGenerator gen)1109 public final void defaultSerializeValue(Object value, JsonGenerator gen) throws IOException 1110 { 1111 if (value == null) { 1112 if (_stdNullValueSerializer) { // minor perf optimization 1113 gen.writeNull(); 1114 } else { 1115 _nullValueSerializer.serialize(null, gen, this); 1116 } 1117 } else { 1118 Class<?> cls = value.getClass(); 1119 findTypedValueSerializer(cls, true, null).serialize(value, gen, this); 1120 } 1121 } 1122 1123 /** 1124 * Convenience method that will serialize given field with specified 1125 * value. Value may be null. Serializer is done using the usual 1126 * null) using standard serializer locating functionality. 1127 */ defaultSerializeField(String fieldName, Object value, JsonGenerator gen)1128 public final void defaultSerializeField(String fieldName, Object value, JsonGenerator gen) 1129 throws IOException 1130 { 1131 gen.writeFieldName(fieldName); 1132 if (value == null) { 1133 /* Note: can't easily check for suppression at this point 1134 * any more; caller must check it. 1135 */ 1136 if (_stdNullValueSerializer) { // minor perf optimization 1137 gen.writeNull(); 1138 } else { 1139 _nullValueSerializer.serialize(null, gen, this); 1140 } 1141 } else { 1142 Class<?> cls = value.getClass(); 1143 findTypedValueSerializer(cls, true, null).serialize(value, gen, this); 1144 } 1145 } 1146 1147 /** 1148 * Method that will handle serialization of Date(-like) values, using 1149 * {@link SerializationConfig} settings to determine expected serialization 1150 * behavior. 1151 * Note: date here means "full" date, that is, date AND time, as per 1152 * Java convention (and not date-only values like in SQL) 1153 */ defaultSerializeDateValue(long timestamp, JsonGenerator gen)1154 public final void defaultSerializeDateValue(long timestamp, JsonGenerator gen) 1155 throws IOException 1156 { 1157 if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) { 1158 gen.writeNumber(timestamp); 1159 } else { 1160 gen.writeString(_dateFormat().format(new Date(timestamp))); 1161 } 1162 } 1163 1164 /** 1165 * Method that will handle serialization of Date(-like) values, using 1166 * {@link SerializationConfig} settings to determine expected serialization 1167 * behavior. 1168 * Note: date here means "full" date, that is, date AND time, as per 1169 * Java convention (and not date-only values like in SQL) 1170 */ defaultSerializeDateValue(Date date, JsonGenerator gen)1171 public final void defaultSerializeDateValue(Date date, JsonGenerator gen) throws IOException 1172 { 1173 if (isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)) { 1174 gen.writeNumber(date.getTime()); 1175 } else { 1176 gen.writeString(_dateFormat().format(date)); 1177 } 1178 } 1179 1180 /** 1181 * Method that will handle serialization of Dates used as {@link java.util.Map} keys, 1182 * based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS} 1183 * value (and if using textual representation, configured date format) 1184 */ defaultSerializeDateKey(long timestamp, JsonGenerator gen)1185 public void defaultSerializeDateKey(long timestamp, JsonGenerator gen) throws IOException 1186 { 1187 if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { 1188 gen.writeFieldName(String.valueOf(timestamp)); 1189 } else { 1190 gen.writeFieldName(_dateFormat().format(new Date(timestamp))); 1191 } 1192 } 1193 1194 /** 1195 * Method that will handle serialization of Dates used as {@link java.util.Map} keys, 1196 * based on {@link SerializationFeature#WRITE_DATE_KEYS_AS_TIMESTAMPS} 1197 * value (and if using textual representation, configured date format) 1198 */ defaultSerializeDateKey(Date date, JsonGenerator gen)1199 public void defaultSerializeDateKey(Date date, JsonGenerator gen) throws IOException 1200 { 1201 if (isEnabled(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { 1202 gen.writeFieldName(String.valueOf(date.getTime())); 1203 } else { 1204 gen.writeFieldName(_dateFormat().format(date)); 1205 } 1206 } 1207 defaultSerializeNull(JsonGenerator gen)1208 public final void defaultSerializeNull(JsonGenerator gen) throws IOException 1209 { 1210 if (_stdNullValueSerializer) { // minor perf optimization 1211 gen.writeNull(); 1212 } else { 1213 _nullValueSerializer.serialize(null, gen, this); 1214 } 1215 } 1216 1217 /* 1218 /******************************************************** 1219 /* Error reporting 1220 /******************************************************** 1221 */ 1222 1223 /** 1224 * Helper method called to indicate problem; default behavior is to construct and 1225 * throw a {@link JsonMappingException}, but in future may collect more than one 1226 * and only throw after certain number, or at the end of serialization. 1227 * 1228 * @since 2.8 1229 */ reportMappingProblem(String message, Object... args)1230 public void reportMappingProblem(String message, Object... args) throws JsonMappingException { 1231 throw mappingException(message, args); 1232 } 1233 1234 /** 1235 * Helper method called to indicate problem in POJO (serialization) definitions or settings 1236 * regarding specific Java type, unrelated to actual JSON content to map. 1237 * Default behavior is to construct and throw a {@link JsonMappingException}. 1238 * 1239 * @since 2.9 1240 */ reportBadTypeDefinition(BeanDescription bean, String msg, Object... msgArgs)1241 public <T> T reportBadTypeDefinition(BeanDescription bean, 1242 String msg, Object... msgArgs) throws JsonMappingException { 1243 String beanDesc = "N/A"; 1244 if (bean != null) { 1245 beanDesc = ClassUtil.nameOf(bean.getBeanClass()); 1246 } 1247 msg = String.format("Invalid type definition for type %s: %s", 1248 beanDesc, _format(msg, msgArgs)); 1249 throw InvalidDefinitionException.from(getGenerator(), msg, bean, null); 1250 } 1251 1252 /** 1253 * Helper method called to indicate problem in POJO (serialization) definitions or settings 1254 * regarding specific property (of a type), unrelated to actual JSON content to map. 1255 * Default behavior is to construct and throw a {@link JsonMappingException}. 1256 * 1257 * @since 2.9 1258 */ reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop, String message, Object... msgArgs)1259 public <T> T reportBadPropertyDefinition(BeanDescription bean, BeanPropertyDefinition prop, 1260 String message, Object... msgArgs) throws JsonMappingException { 1261 message = _format(message, msgArgs); 1262 String propName = "N/A"; 1263 if (prop != null) { 1264 propName = _quotedString(prop.getName()); 1265 } 1266 String beanDesc = "N/A"; 1267 if (bean != null) { 1268 beanDesc = ClassUtil.nameOf(bean.getBeanClass()); 1269 } 1270 message = String.format("Invalid definition for property %s (of type %s): %s", 1271 propName, beanDesc, message); 1272 throw InvalidDefinitionException.from(getGenerator(), message, bean, prop); 1273 } 1274 1275 @Override reportBadDefinition(JavaType type, String msg)1276 public <T> T reportBadDefinition(JavaType type, String msg) throws JsonMappingException { 1277 throw InvalidDefinitionException.from(getGenerator(), msg, type); 1278 } 1279 1280 /** 1281 * @since 2.9 1282 */ reportBadDefinition(JavaType type, String msg, Throwable cause)1283 public <T> T reportBadDefinition(JavaType type, String msg, Throwable cause) 1284 throws JsonMappingException { 1285 InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, type); 1286 e.initCause(cause); 1287 throw e; 1288 } 1289 1290 /** 1291 * @since 2.9 1292 */ reportBadDefinition(Class<?> raw, String msg, Throwable cause)1293 public <T> T reportBadDefinition(Class<?> raw, String msg, Throwable cause) 1294 throws JsonMappingException { 1295 InvalidDefinitionException e = InvalidDefinitionException.from(getGenerator(), msg, constructType(raw)); 1296 e.initCause(cause); 1297 throw e; 1298 } 1299 1300 /** 1301 * Helper method called to indicate problem; default behavior is to construct and 1302 * throw a {@link JsonMappingException}, but in future may collect more than one 1303 * and only throw after certain number, or at the end of serialization. 1304 * 1305 * @since 2.8 1306 */ reportMappingProblem(Throwable t, String message, Object... msgArgs)1307 public void reportMappingProblem(Throwable t, String message, Object... msgArgs) throws JsonMappingException { 1308 message = _format(message, msgArgs); 1309 throw JsonMappingException.from(getGenerator(), message, t); 1310 } 1311 1312 @Override invalidTypeIdException(JavaType baseType, String typeId, String extraDesc)1313 public JsonMappingException invalidTypeIdException(JavaType baseType, String typeId, 1314 String extraDesc) { 1315 String msg = String.format("Could not resolve type id '%s' as a subtype of %s", 1316 typeId, ClassUtil.getTypeDescription(baseType)); 1317 return InvalidTypeIdException.from(null, _colonConcat(msg, extraDesc), baseType, typeId); 1318 } 1319 1320 /* 1321 /******************************************************** 1322 /* Error reporting, deprecated methods 1323 /******************************************************** 1324 */ 1325 1326 /** 1327 * Factory method for constructing a {@link JsonMappingException}; 1328 * usually only indirectly used by calling 1329 * {@link #reportMappingProblem(String, Object...)}. 1330 * 1331 * @since 2.6 1332 * 1333 * @deprecated Since 2.9 1334 */ 1335 @Deprecated // since 2.9 mappingException(String message, Object... msgArgs)1336 public JsonMappingException mappingException(String message, Object... msgArgs) { 1337 return JsonMappingException.from(getGenerator(), _format(message, msgArgs)); 1338 } 1339 1340 /** 1341 * Factory method for constructing a {@link JsonMappingException}; 1342 * usually only indirectly used by calling 1343 * {@link #reportMappingProblem(Throwable, String, Object...)} 1344 * 1345 * @since 2.8 1346 * 1347 * @deprecated Since 2.9 1348 */ 1349 @Deprecated // since 2.9 mappingException(Throwable t, String message, Object... msgArgs)1350 protected JsonMappingException mappingException(Throwable t, String message, Object... msgArgs) { 1351 return JsonMappingException.from(getGenerator(), _format(message, msgArgs), t); 1352 } 1353 1354 /* 1355 /******************************************************** 1356 /* Helper methods 1357 /******************************************************** 1358 */ 1359 _reportIncompatibleRootType(Object value, JavaType rootType)1360 protected void _reportIncompatibleRootType(Object value, JavaType rootType) throws IOException 1361 { 1362 // One special case: allow primitive/wrapper type coercion 1363 if (rootType.isPrimitive()) { 1364 Class<?> wrapperType = ClassUtil.wrapperType(rootType.getRawClass()); 1365 // If it's just difference between wrapper, primitive, let it slide 1366 if (wrapperType.isAssignableFrom(value.getClass())) { 1367 return; 1368 } 1369 } 1370 reportBadDefinition(rootType, String.format( 1371 "Incompatible types: declared root type (%s) vs %s", 1372 rootType, ClassUtil.classNameOf(value))); 1373 } 1374 1375 /** 1376 * Method that will try to find a serializer, either from cache 1377 * or by constructing one; but will not return an "unknown" serializer 1378 * if this cannot be done but rather returns null. 1379 * 1380 * @return Serializer if one can be found, null if not. 1381 */ _findExplicitUntypedSerializer(Class<?> runtimeType)1382 protected JsonSerializer<Object> _findExplicitUntypedSerializer(Class<?> runtimeType) 1383 throws JsonMappingException 1384 { 1385 // Fast lookup from local lookup thingy works? 1386 JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(runtimeType); 1387 if (ser == null) { 1388 // If not, maybe shared map already has it? 1389 ser = _serializerCache.untypedValueSerializer(runtimeType); 1390 if (ser == null) { 1391 ser = _createAndCacheUntypedSerializer(runtimeType); 1392 } 1393 } 1394 /* 18-Sep-2014, tatu: This is unfortunate patch over related change 1395 * that pushes creation of "unknown type" serializer deeper down 1396 * in BeanSerializerFactory; as a result, we need to "undo" creation 1397 * here. 1398 */ 1399 if (isUnknownTypeSerializer(ser)) { 1400 return null; 1401 } 1402 return ser; 1403 } 1404 1405 /* 1406 /********************************************************** 1407 /* Low-level methods for actually constructing and initializing 1408 /* serializers 1409 /********************************************************** 1410 */ 1411 1412 /** 1413 * Method that will try to construct a value serializer; and if 1414 * one is successfully created, cache it for reuse. 1415 */ _createAndCacheUntypedSerializer(Class<?> rawType)1416 protected JsonSerializer<Object> _createAndCacheUntypedSerializer(Class<?> rawType) 1417 throws JsonMappingException 1418 { 1419 JavaType fullType = _config.constructType(rawType); 1420 JsonSerializer<Object> ser; 1421 try { 1422 ser = _createUntypedSerializer(fullType); 1423 } catch (IllegalArgumentException iae) { 1424 // We better only expose checked exceptions, since those 1425 // are what caller is expected to handle 1426 ser = null; // doesn't matter but compiler whines otherwise 1427 reportMappingProblem(iae, ClassUtil.exceptionMessage(iae)); 1428 } 1429 1430 if (ser != null) { 1431 // 21-Dec-2015, tatu: Best to cache for both raw and full-type key 1432 _serializerCache.addAndResolveNonTypedSerializer(rawType, fullType, ser, this); 1433 } 1434 return ser; 1435 } 1436 _createAndCacheUntypedSerializer(JavaType type)1437 protected JsonSerializer<Object> _createAndCacheUntypedSerializer(JavaType type) 1438 throws JsonMappingException 1439 { 1440 JsonSerializer<Object> ser; 1441 try { 1442 ser = _createUntypedSerializer(type); 1443 } catch (IllegalArgumentException iae) { 1444 // We better only expose checked exceptions, since those 1445 // are what caller is expected to handle 1446 ser = null; 1447 reportMappingProblem(iae, ClassUtil.exceptionMessage(iae)); 1448 } 1449 1450 if (ser != null) { 1451 // 21-Dec-2015, tatu: Should we also cache using raw key? 1452 _serializerCache.addAndResolveNonTypedSerializer(type, ser, this); 1453 } 1454 return ser; 1455 } 1456 1457 /** 1458 * @since 2.1 1459 */ _createUntypedSerializer(JavaType type)1460 protected JsonSerializer<Object> _createUntypedSerializer(JavaType type) 1461 throws JsonMappingException 1462 { 1463 /* 27-Mar-2015, tatu: Wish I knew exactly why/what, but [databind#738] 1464 * can be prevented by synchronizing on cache (not on 'this', however, 1465 * since there's one instance per serialization). 1466 * Perhaps not-yet-resolved instance might be exposed too early to callers. 1467 */ 1468 // 13-Apr-2018, tatu: Problem does NOT occur any more with late 2.8.x and 2.9.x 1469 // versions, likely due to concurrency fixes for `AnnotatedClass` introspection. 1470 // This sync block could probably be removed; but to minimize any risk of 1471 // regression sync block will only be removed from 3.0. 1472 // 23-Oct-2019, tatu: Due to continuation of 2.x line, removed from 2.11 1473 // synchronized (_serializerCache) { 1474 return (JsonSerializer<Object>)_serializerFactory.createSerializer(this, type); 1475 // } 1476 } 1477 1478 /** 1479 * Helper method called to resolve and contextualize given 1480 * serializer, if and as necessary. 1481 */ 1482 @SuppressWarnings("unchecked") _handleContextualResolvable(JsonSerializer<?> ser, BeanProperty property)1483 protected JsonSerializer<Object> _handleContextualResolvable(JsonSerializer<?> ser, 1484 BeanProperty property) 1485 throws JsonMappingException 1486 { 1487 if (ser instanceof ResolvableSerializer) { 1488 ((ResolvableSerializer) ser).resolve(this); 1489 } 1490 return (JsonSerializer<Object>) handleSecondaryContextualization(ser, property); 1491 } 1492 1493 @SuppressWarnings("unchecked") _handleResolvable(JsonSerializer<?> ser)1494 protected JsonSerializer<Object> _handleResolvable(JsonSerializer<?> ser) 1495 throws JsonMappingException 1496 { 1497 if (ser instanceof ResolvableSerializer) { 1498 ((ResolvableSerializer) ser).resolve(this); 1499 } 1500 return (JsonSerializer<Object>) ser; 1501 } 1502 1503 /* 1504 /********************************************************** 1505 /* Internal methods 1506 /********************************************************** 1507 */ 1508 _dateFormat()1509 protected final DateFormat _dateFormat() 1510 { 1511 if (_dateFormat != null) { 1512 return _dateFormat; 1513 } 1514 /* At this point, all timezone configuration should have occurred, with respect 1515 * to default dateformat configuration. But we still better clone 1516 * an instance as formatters are stateful, not thread-safe. 1517 */ 1518 DateFormat df = _config.getDateFormat(); 1519 _dateFormat = df = (DateFormat) df.clone(); 1520 // [databind#939]: 26-Sep-2015, tatu: With 2.6, formatter has been (pre)configured 1521 // with TimeZone, so we should NOT try overriding it unlike with earlier versions 1522 /* 1523 TimeZone tz = getTimeZone(); 1524 if (tz != df.getTimeZone()) { 1525 df.setTimeZone(tz); 1526 } 1527 */ 1528 return df; 1529 } 1530 } 1531