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