• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.deser;
2 
3 import java.io.Serializable;
4 import java.math.BigDecimal;
5 import java.math.BigInteger;
6 import java.util.*;
7 import java.util.concurrent.*;
8 import java.util.concurrent.atomic.AtomicReference;
9 
10 import com.fasterxml.jackson.annotation.JacksonInject;
11 import com.fasterxml.jackson.annotation.JsonCreator;
12 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
13 import com.fasterxml.jackson.annotation.JsonIncludeProperties;
14 import com.fasterxml.jackson.annotation.JsonSetter;
15 import com.fasterxml.jackson.annotation.Nulls;
16 import com.fasterxml.jackson.annotation.JsonCreator.Mode;
17 
18 import com.fasterxml.jackson.core.JsonParser;
19 
20 import com.fasterxml.jackson.databind.*;
21 import com.fasterxml.jackson.databind.cfg.ConfigOverride;
22 import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
23 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
24 import com.fasterxml.jackson.databind.deser.impl.CreatorCandidate;
25 import com.fasterxml.jackson.databind.deser.impl.CreatorCollector;
26 import com.fasterxml.jackson.databind.deser.impl.JDKValueInstantiators;
27 import com.fasterxml.jackson.databind.deser.impl.JavaUtilCollectionsDeserializers;
28 import com.fasterxml.jackson.databind.deser.std.*;
29 import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
30 import com.fasterxml.jackson.databind.ext.OptionalHandlerFactory;
31 import com.fasterxml.jackson.databind.introspect.*;
32 import com.fasterxml.jackson.databind.jsontype.NamedType;
33 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
34 import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
35 import com.fasterxml.jackson.databind.type.*;
36 import com.fasterxml.jackson.databind.util.*;
37 
38 /**
39  * Abstract factory base class that can provide deserializers for standard
40  * JDK classes, including collection classes and simple heuristics for
41  * "upcasting" common collection interface types
42  * (such as {@link java.util.Collection}).
43  *<p>
44  * Since all simple deserializers are eagerly instantiated, and there is
45  * no additional introspection or customizability of these types,
46  * this factory is stateless.
47  */
48 @SuppressWarnings("serial")
49 public abstract class BasicDeserializerFactory
50     extends DeserializerFactory
51     implements java.io.Serializable
52 {
53     private final static Class<?> CLASS_OBJECT = Object.class;
54     private final static Class<?> CLASS_STRING = String.class;
55     private final static Class<?> CLASS_CHAR_SEQUENCE = CharSequence.class;
56     private final static Class<?> CLASS_ITERABLE = Iterable.class;
57     private final static Class<?> CLASS_MAP_ENTRY = Map.Entry.class;
58     private final static Class<?> CLASS_SERIALIZABLE = Serializable.class;
59 
60     /**
61      * We need a placeholder for creator properties that don't have name
62      * but are marked with `@JsonWrapped` annotation.
63      */
64     protected final static PropertyName UNWRAPPED_CREATOR_PARAM_NAME = new PropertyName("@JsonUnwrapped");
65 
66     /*
67     /**********************************************************
68     /* Config
69     /**********************************************************
70      */
71 
72     /**
73      * Configuration settings for this factory; immutable instance (just like this
74      * factory), new version created via copy-constructor (fluent-style)
75      */
76     protected final DeserializerFactoryConfig _factoryConfig;
77 
78     /*
79     /**********************************************************
80     /* Life cycle
81     /**********************************************************
82      */
83 
BasicDeserializerFactory(DeserializerFactoryConfig config)84     protected BasicDeserializerFactory(DeserializerFactoryConfig config) {
85         _factoryConfig = config;
86     }
87 
88     /**
89      * Method for getting current {@link DeserializerFactoryConfig}.
90       *<p>
91      * Note that since instances are immutable, you can NOT change settings
92      * by accessing an instance and calling methods: this will simply create
93      * new instance of config object.
94      */
getFactoryConfig()95     public DeserializerFactoryConfig getFactoryConfig() {
96         return _factoryConfig;
97     }
98 
withConfig(DeserializerFactoryConfig config)99     protected abstract DeserializerFactory withConfig(DeserializerFactoryConfig config);
100 
101     /*
102     /********************************************************
103     /* Configuration handling: fluent factories
104     /********************************************************
105      */
106 
107     /**
108      * Convenience method for creating a new factory instance with additional deserializer
109      * provider.
110      */
111     @Override
withAdditionalDeserializers(Deserializers additional)112     public final DeserializerFactory withAdditionalDeserializers(Deserializers additional) {
113         return withConfig(_factoryConfig.withAdditionalDeserializers(additional));
114     }
115 
116     /**
117      * Convenience method for creating a new factory instance with additional
118      * {@link KeyDeserializers}.
119      */
120     @Override
withAdditionalKeyDeserializers(KeyDeserializers additional)121     public final DeserializerFactory withAdditionalKeyDeserializers(KeyDeserializers additional) {
122         return withConfig(_factoryConfig.withAdditionalKeyDeserializers(additional));
123     }
124 
125     /**
126      * Convenience method for creating a new factory instance with additional
127      * {@link BeanDeserializerModifier}.
128      */
129     @Override
withDeserializerModifier(BeanDeserializerModifier modifier)130     public final DeserializerFactory withDeserializerModifier(BeanDeserializerModifier modifier) {
131         return withConfig(_factoryConfig.withDeserializerModifier(modifier));
132     }
133 
134     /**
135      * Convenience method for creating a new factory instance with additional
136      * {@link AbstractTypeResolver}.
137      */
138     @Override
withAbstractTypeResolver(AbstractTypeResolver resolver)139     public final DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver) {
140         return withConfig(_factoryConfig.withAbstractTypeResolver(resolver));
141     }
142 
143     /**
144      * Convenience method for creating a new factory instance with additional
145      * {@link ValueInstantiators}.
146      */
147     @Override
withValueInstantiators(ValueInstantiators instantiators)148     public final DeserializerFactory withValueInstantiators(ValueInstantiators instantiators) {
149         return withConfig(_factoryConfig.withValueInstantiators(instantiators));
150     }
151 
152     /*
153     /**********************************************************
154     /* DeserializerFactory impl (partial): type mappings
155     /**********************************************************
156      */
157 
158     @Override
mapAbstractType(DeserializationConfig config, JavaType type)159     public JavaType mapAbstractType(DeserializationConfig config, JavaType type) throws JsonMappingException
160     {
161         // first, general mappings
162         while (true) {
163             JavaType next = _mapAbstractType2(config, type);
164             if (next == null) {
165                 return type;
166             }
167             // Should not have to worry about cycles; but better verify since they will invariably occur... :-)
168             // (also: guard against invalid resolution to a non-related type)
169             Class<?> prevCls = type.getRawClass();
170             Class<?> nextCls = next.getRawClass();
171             if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) {
172                 throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former");
173             }
174             type = next;
175         }
176     }
177 
178     /**
179      * Method that will find abstract type mapping for specified type, doing a single
180      * lookup through registered abstract type resolvers; will not do recursive lookups.
181      */
_mapAbstractType2(DeserializationConfig config, JavaType type)182     private JavaType _mapAbstractType2(DeserializationConfig config, JavaType type)
183         throws JsonMappingException
184     {
185         Class<?> currClass = type.getRawClass();
186         if (_factoryConfig.hasAbstractTypeResolvers()) {
187             for (AbstractTypeResolver resolver : _factoryConfig.abstractTypeResolvers()) {
188                 JavaType concrete = resolver.findTypeMapping(config, type);
189                 if ((concrete != null) && !concrete.hasRawClass(currClass)) {
190                     return concrete;
191                 }
192             }
193         }
194         return null;
195     }
196 
197     /*
198     /**********************************************************
199     /* DeserializerFactory impl (partial): ValueInstantiators
200     /**********************************************************
201      */
202 
203     /**
204      * Value instantiator is created both based on creator annotations,
205      * and on optional externally provided instantiators (registered through
206      * module interface).
207      */
208     @Override
findValueInstantiator(DeserializationContext ctxt, BeanDescription beanDesc)209     public ValueInstantiator findValueInstantiator(DeserializationContext ctxt,
210             BeanDescription beanDesc)
211         throws JsonMappingException
212     {
213         final DeserializationConfig config = ctxt.getConfig();
214 
215         ValueInstantiator instantiator = null;
216         // Check @JsonValueInstantiator before anything else
217         AnnotatedClass ac = beanDesc.getClassInfo();
218         Object instDef = ctxt.getAnnotationIntrospector().findValueInstantiator(ac);
219         if (instDef != null) {
220             instantiator = _valueInstantiatorInstance(config, ac, instDef);
221         }
222         if (instantiator == null) {
223             // Second: see if some of standard Jackson/JDK types might provide value
224             // instantiators.
225             instantiator = JDKValueInstantiators.findStdValueInstantiator(config, beanDesc.getBeanClass());
226             if (instantiator == null) {
227                 instantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
228             }
229         }
230 
231         // finally: anyone want to modify ValueInstantiator?
232         if (_factoryConfig.hasValueInstantiators()) {
233             for (ValueInstantiators insts : _factoryConfig.valueInstantiators()) {
234                 instantiator = insts.findValueInstantiator(config, beanDesc, instantiator);
235                 // let's do sanity check; easier to spot buggy handlers
236                 if (instantiator == null) {
237                     ctxt.reportBadTypeDefinition(beanDesc,
238 						"Broken registered ValueInstantiators (of type %s): returned null ValueInstantiator",
239 						insts.getClass().getName());
240                 }
241             }
242         }
243         if (instantiator != null) {
244             instantiator = instantiator.createContextual(ctxt, beanDesc);
245         }
246 
247         return instantiator;
248     }
249 
250     /**
251      * Method that will construct standard default {@link ValueInstantiator}
252      * using annotations (like @JsonCreator) and visibility rules
253      */
_constructDefaultValueInstantiator(DeserializationContext ctxt, BeanDescription beanDesc)254     protected ValueInstantiator _constructDefaultValueInstantiator(DeserializationContext ctxt,
255             BeanDescription beanDesc)
256         throws JsonMappingException
257     {
258         CreatorCollector creators = new CreatorCollector(beanDesc, ctxt.getConfig());
259         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
260 
261         // need to construct suitable visibility checker:
262         final DeserializationConfig config = ctxt.getConfig();
263         VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker(beanDesc.getBeanClass(),
264                 beanDesc.getClassInfo());
265 
266         /* 24-Sep-2014, tatu: Tricky part first; need to merge resolved property information
267          *  (which has creator parameters sprinkled around) with actual creator
268          *  declarations (which are needed to access creator annotation, amongst other things).
269          *  Easiest to combine that info first, then pass it to remaining processing.
270          */
271         /* 15-Mar-2015, tatu: Alas, this won't help with constructors that only have implicit
272          *   names. Those will need to be resolved later on.
273          */
274         Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorDefs = _findCreatorsFromProperties(ctxt,
275                 beanDesc);
276         // Important: first add factory methods; then constructors, so
277         // latter can override former!
278         _addDeserializerFactoryMethods(ctxt, beanDesc, vchecker, intr, creators, creatorDefs);
279         // constructors only usable on concrete types:
280         if (beanDesc.getType().isConcrete()) {
281             _addDeserializerConstructors(ctxt, beanDesc, vchecker, intr, creators, creatorDefs);
282         }
283         return creators.constructValueInstantiator(ctxt);
284     }
285 
_findCreatorsFromProperties(DeserializationContext ctxt, BeanDescription beanDesc)286     protected Map<AnnotatedWithParams,BeanPropertyDefinition[]> _findCreatorsFromProperties(DeserializationContext ctxt,
287             BeanDescription beanDesc) throws JsonMappingException
288     {
289         Map<AnnotatedWithParams,BeanPropertyDefinition[]> result = Collections.emptyMap();
290         for (BeanPropertyDefinition propDef : beanDesc.findProperties()) {
291             Iterator<AnnotatedParameter> it = propDef.getConstructorParameters();
292             while (it.hasNext()) {
293                 AnnotatedParameter param = it.next();
294                 AnnotatedWithParams owner = param.getOwner();
295                 BeanPropertyDefinition[] defs = result.get(owner);
296                 final int index = param.getIndex();
297 
298                 if (defs == null) {
299                     if (result.isEmpty()) { // since emptyMap is immutable need to create a 'real' one
300                         result = new LinkedHashMap<AnnotatedWithParams,BeanPropertyDefinition[]>();
301                     }
302                     defs = new BeanPropertyDefinition[owner.getParameterCount()];
303                     result.put(owner, defs);
304                 } else {
305                     if (defs[index] != null) {
306                         ctxt.reportBadTypeDefinition(beanDesc,
307 "Conflict: parameter #%d of %s bound to more than one property; %s vs %s",
308 index, owner, defs[index], propDef);
309                     }
310                 }
311                 defs[index] = propDef;
312             }
313         }
314         return result;
315     }
316 
_valueInstantiatorInstance(DeserializationConfig config, Annotated annotated, Object instDef)317     public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config,
318             Annotated annotated, Object instDef)
319         throws JsonMappingException
320     {
321         if (instDef == null) {
322             return null;
323         }
324 
325         ValueInstantiator inst;
326 
327         if (instDef instanceof ValueInstantiator) {
328             return (ValueInstantiator) instDef;
329         }
330         if (!(instDef instanceof Class)) {
331             throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
332                     +instDef.getClass().getName()
333                     +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
334         }
335         Class<?> instClass = (Class<?>)instDef;
336         if (ClassUtil.isBogusClass(instClass)) {
337             return null;
338         }
339         if (!ValueInstantiator.class.isAssignableFrom(instClass)) {
340             throw new IllegalStateException("AnnotationIntrospector returned Class "+instClass.getName()
341                     +"; expected Class<ValueInstantiator>");
342         }
343         HandlerInstantiator hi = config.getHandlerInstantiator();
344         if (hi != null) {
345             inst = hi.valueInstantiatorInstance(config, annotated, instClass);
346             if (inst != null) {
347                 return inst;
348             }
349         }
350         return (ValueInstantiator) ClassUtil.createInstance(instClass,
351                 config.canOverrideAccessModifiers());
352     }
353 
354     /*
355     /**********************************************************
356     /* Creator introspection
357     /**********************************************************
358      */
359 
_addDeserializerConstructors(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker, AnnotationIntrospector intr, CreatorCollector creators, Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)360     protected void _addDeserializerConstructors(DeserializationContext ctxt,
361             BeanDescription beanDesc, VisibilityChecker<?> vchecker,
362          AnnotationIntrospector intr, CreatorCollector creators,
363          Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)
364                  throws JsonMappingException
365     {
366         // 25-Jan-2017, tatu: As per [databind#1501], [databind#1502], [databind#1503], best
367         //     for now to skip attempts at using anything but no-args constructor (see
368         //     `InnerClassProperty` construction for that)
369         final boolean isNonStaticInnerClass = beanDesc.isNonStaticInnerClass();
370         if (isNonStaticInnerClass) {
371             // TODO: look for `@JsonCreator` annotated ones, throw explicit exception?
372             return;
373         }
374 
375         // First things first: the "default constructor" (zero-arg
376         // constructor; whether implicit or explicit) is NOT included
377         // in list of constructors, so needs to be handled separately.
378         AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor();
379         if (defaultCtor != null) {
380             if (!creators.hasDefaultCreator() || _hasCreatorAnnotation(ctxt, defaultCtor)) {
381                 creators.setDefaultCreator(defaultCtor);
382             }
383         }
384         // 21-Sep-2017, tatu: First let's handle explicitly annotated ones
385         List<CreatorCandidate> nonAnnotated = new LinkedList<>();
386         int explCount = 0;
387         for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
388             JsonCreator.Mode creatorMode = intr.findCreatorAnnotation(ctxt.getConfig(), ctor);
389             if (Mode.DISABLED == creatorMode) {
390                 continue;
391             }
392             if (creatorMode == null) {
393                 // let's check Visibility here, to avoid further processing for non-visible?
394                 if (vchecker.isCreatorVisible(ctor)) {
395                     nonAnnotated.add(CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor)));
396                 }
397                 continue;
398             }
399             switch (creatorMode) {
400             case DELEGATING:
401                 _addExplicitDelegatingCreator(ctxt, beanDesc, creators,
402                         CreatorCandidate.construct(intr, ctor, null));
403                 break;
404             case PROPERTIES:
405                 _addExplicitPropertyCreator(ctxt, beanDesc, creators,
406                         CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor)));
407                 break;
408             default:
409                 _addExplicitAnyCreator(ctxt, beanDesc, creators,
410                         CreatorCandidate.construct(intr, ctor, creatorParams.get(ctor)));
411                 break;
412             }
413             ++explCount;
414         }
415         // And only if and when those handled, consider potentially visible ones
416         if (explCount > 0) { // TODO: split method into two since we could have expl factories
417             return;
418         }
419         List<AnnotatedWithParams> implicitCtors = null;
420         for (CreatorCandidate candidate : nonAnnotated) {
421             final int argCount = candidate.paramCount();
422             final AnnotatedWithParams ctor = candidate.creator();
423 
424             // some single-arg factory methods (String, number) are auto-detected
425             if (argCount == 1) {
426                 BeanPropertyDefinition propDef = candidate.propertyDef(0);
427                 boolean useProps = _checkIfCreatorPropertyBased(intr, ctor, propDef);
428 
429                 if (useProps) {
430                     SettableBeanProperty[] properties = new SettableBeanProperty[1];
431                     PropertyName name = candidate.paramName(0);
432                     properties[0] = constructCreatorProperty(ctxt, beanDesc, name, 0,
433                             candidate.parameter(0), candidate.injection(0));
434                     creators.addPropertyCreator(ctor, false, properties);
435                 } else {
436                     /*boolean added = */ _handleSingleArgumentCreator(creators,
437                             ctor, false,
438                             vchecker.isCreatorVisible(ctor));
439                     // one more thing: sever link to creator property, to avoid possible later
440                     // problems with "unresolved" constructor property
441                     if (propDef != null) {
442                         ((POJOPropertyBuilder) propDef).removeConstructors();
443                     }
444                 }
445                 // regardless, fully handled
446                 continue;
447             }
448 
449             // 2 or more args; all params must have names or be injectable
450             // 14-Mar-2015, tatu (2.6): Or, as per [#725], implicit names will also
451             //   do, with some constraints. But that will require bit post processing...
452 
453             int nonAnnotatedParamIndex = -1;
454             SettableBeanProperty[] properties = new SettableBeanProperty[argCount];
455             int explicitNameCount = 0;
456             int implicitWithCreatorCount = 0;
457             int injectCount = 0;
458 
459             for (int i = 0; i < argCount; ++i) {
460                 final AnnotatedParameter param = ctor.getParameter(i);
461                 BeanPropertyDefinition propDef = candidate.propertyDef(i);
462                 JacksonInject.Value injectable = intr.findInjectableValue(param);
463                 final PropertyName name = (propDef == null) ? null : propDef.getFullName();
464 
465                 if (propDef != null && propDef.isExplicitlyNamed()) {
466                     ++explicitNameCount;
467                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable);
468                     continue;
469                 }
470                 if (injectable != null) {
471                     ++injectCount;
472                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable);
473                     continue;
474                 }
475                 NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
476                 if (unwrapper != null) {
477                     _reportUnwrappedCreatorProperty(ctxt, beanDesc, param);
478                     /*
479                     properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
480                     ++explicitNameCount;
481                     */
482                     continue;
483                 }
484                 // One more thing: implicit names are ok iff ctor has creator annotation
485                 /*
486                 if (isCreator && (name != null && !name.isEmpty())) {
487                     ++implicitWithCreatorCount;
488                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
489                     continue;
490                 }
491                 */
492                 if (nonAnnotatedParamIndex < 0) {
493                     nonAnnotatedParamIndex = i;
494                 }
495             }
496 
497             final int namedCount = explicitNameCount + implicitWithCreatorCount;
498             // Ok: if named or injectable, we have more work to do
499             if ((explicitNameCount > 0) || (injectCount > 0)) {
500                 // simple case; everything covered:
501                 if ((namedCount + injectCount) == argCount) {
502                     creators.addPropertyCreator(ctor, false, properties);
503                     continue;
504                 }
505                 if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) {
506                     // Secondary: all but one injectable, one un-annotated (un-named)
507                     creators.addDelegatingCreator(ctor, false, properties, 0);
508                     continue;
509                 }
510                 // otherwise, epic fail?
511                 // 16-Mar-2015, tatu: due to [#725], need to be more permissive. For now let's
512                 //    only report problem if there's no implicit name
513                 PropertyName impl = candidate.findImplicitParamName(nonAnnotatedParamIndex);
514                 if (impl == null || impl.isEmpty()) {
515                     // Let's consider non-static inner class as a special case...
516                     // 25-Jan-2017, tatu: Non-static inner classes skipped altogether, now
517                     /*
518                     if ((nonAnnotatedParamIndex == 0) && isNonStaticInnerClass) {
519                         throw new IllegalArgumentException("Non-static inner classes like "
520                                 +ctor.getDeclaringClass().getName()+" cannot use @JsonCreator for constructors");
521                     }
522                     */
523                     ctxt.reportBadTypeDefinition(beanDesc,
524 "Argument #%d of constructor %s has no property name annotation; must have name when multiple-parameter constructor annotated as Creator",
525 nonAnnotatedParamIndex, ctor);
526                 }
527             }
528             // [#725]: as a fallback, all-implicit names may work as well
529             if (!creators.hasDefaultCreator()) {
530                 if (implicitCtors == null) {
531                     implicitCtors = new LinkedList<>();
532                 }
533                 implicitCtors.add(ctor);
534             }
535         }
536         // last option, as per [#725]: consider implicit-names-only, visible constructor,
537         // if just one found
538         if ((implicitCtors != null) && !creators.hasDelegatingCreator()
539                 && !creators.hasPropertyBasedCreator()) {
540             _checkImplicitlyNamedConstructors(ctxt, beanDesc, vchecker, intr,
541                     creators, implicitCtors);
542         }
543     }
544 
545     /**
546      * Helper method called when there is the explicit "is-creator" with mode of "delegating"
547      *
548      * @since 2.9.2
549      */
_addExplicitDelegatingCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate)550     protected void _addExplicitDelegatingCreator(DeserializationContext ctxt,
551             BeanDescription beanDesc, CreatorCollector creators,
552             CreatorCandidate candidate)
553         throws JsonMappingException
554     {
555         // Somewhat simple: find injectable values, if any, ensure there is one
556         // and just one delegated argument; report violations if any
557 
558         int ix = -1;
559         final int argCount = candidate.paramCount();
560         SettableBeanProperty[] properties = new SettableBeanProperty[argCount];
561         for (int i = 0; i < argCount; ++i) {
562             AnnotatedParameter param = candidate.parameter(i);
563             JacksonInject.Value injectId = candidate.injection(i);
564             if (injectId != null) {
565                 properties[i] = constructCreatorProperty(ctxt, beanDesc, null, i, param, injectId);
566                 continue;
567             }
568             if (ix < 0) {
569                 ix = i;
570                 continue;
571             }
572             // Illegal to have more than one value to delegate to
573             ctxt.reportBadTypeDefinition(beanDesc,
574                     "More than one argument (#%d and #%d) left as delegating for Creator %s: only one allowed",
575                     ix, i, candidate);
576         }
577         // Also, let's require that one Delegating argument does eixt
578         if (ix < 0) {
579             ctxt.reportBadTypeDefinition(beanDesc,
580                     "No argument left as delegating for Creator %s: exactly one required", candidate);
581         }
582         // 17-Jan-2018, tatu: as per [databind#1853] need to ensure we will distinguish
583         //   "well-known" single-arg variants (String, int/long, boolean) from "generic" delegating...
584         if (argCount == 1) {
585             _handleSingleArgumentCreator(creators, candidate.creator(), true, true);
586             // one more thing: sever link to creator property, to avoid possible later
587             // problems with "unresolved" constructor property
588             BeanPropertyDefinition paramDef = candidate.propertyDef(0);
589             if (paramDef != null) {
590                 ((POJOPropertyBuilder) paramDef).removeConstructors();
591             }
592             return;
593         }
594         creators.addDelegatingCreator(candidate.creator(), true, properties, ix);
595     }
596 
597     /**
598      * Helper method called when there is the explicit "is-creator" with mode of "properties-based"
599      *
600      * @since 2.9.2
601      */
_addExplicitPropertyCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate)602     protected void _addExplicitPropertyCreator(DeserializationContext ctxt,
603             BeanDescription beanDesc, CreatorCollector creators,
604             CreatorCandidate candidate)
605         throws JsonMappingException
606     {
607         final int paramCount = candidate.paramCount();
608         SettableBeanProperty[] properties = new SettableBeanProperty[paramCount];
609 
610         for (int i = 0; i < paramCount; ++i) {
611             JacksonInject.Value injectId = candidate.injection(i);
612             AnnotatedParameter param = candidate.parameter(i);
613             PropertyName name = candidate.paramName(i);
614             if (name == null) {
615                 // 21-Sep-2017, tatu: Looks like we want to block accidental use of Unwrapped,
616                 //   as that will not work with Creators well at all
617                 NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(param);
618                 if (unwrapper != null) {
619                     _reportUnwrappedCreatorProperty(ctxt, beanDesc, param);
620                     /*
621                     properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
622                     ++explicitNameCount;
623                     */
624                 }
625                 name = candidate.findImplicitParamName(i);
626                 // Must be injectable or have name; without either won't work
627                 if ((name == null) && (injectId == null)) {
628                     ctxt.reportBadTypeDefinition(beanDesc,
629 "Argument #%d has no property name, is not Injectable: can not use as Creator %s", i, candidate);
630                 }
631             }
632             properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectId);
633         }
634         creators.addPropertyCreator(candidate.creator(), true, properties);
635     }
636 
637     /**
638      * Helper method called when there is explicit "is-creator" marker, but no mode declaration.
639      *
640      * @since 2.9.2
641      */
_addExplicitAnyCreator(DeserializationContext ctxt, BeanDescription beanDesc, CreatorCollector creators, CreatorCandidate candidate)642     protected void _addExplicitAnyCreator(DeserializationContext ctxt,
643             BeanDescription beanDesc, CreatorCollector creators,
644             CreatorCandidate candidate)
645         throws JsonMappingException
646     {
647         // Looks like there's bit of magic regarding 1-parameter creators; others simpler:
648         if (1 != candidate.paramCount()) {
649             // Ok: for delegates, we want one and exactly one parameter without
650             // injection AND without name
651             int oneNotInjected = candidate.findOnlyParamWithoutInjection();
652             if (oneNotInjected >= 0) {
653                 // getting close; but most not have name
654                 if (candidate.paramName(oneNotInjected) == null) {
655                     _addExplicitDelegatingCreator(ctxt, beanDesc, creators, candidate);
656                     return;
657                 }
658             }
659             _addExplicitPropertyCreator(ctxt, beanDesc, creators, candidate);
660             return;
661         }
662         AnnotatedParameter param = candidate.parameter(0);
663         JacksonInject.Value injectId = candidate.injection(0);
664         PropertyName paramName = candidate.explicitParamName(0);
665         BeanPropertyDefinition paramDef = candidate.propertyDef(0);
666 
667         // If there's injection or explicit name, should be properties-based
668         boolean useProps = (paramName != null) || (injectId != null);
669         if (!useProps && (paramDef != null)) {
670             // One more thing: if implicit name matches property with a getter
671             // or field, we'll consider it property-based as well
672 
673             // 25-May-2018, tatu: as per [databind#2051], looks like we have to get
674             //    not implicit name, but name with possible strategy-based-rename
675 //            paramName = candidate.findImplicitParamName(0);
676             paramName = candidate.paramName(0);
677             useProps = (paramName != null) && paramDef.couldSerialize();
678         }
679         if (useProps) {
680             SettableBeanProperty[] properties = new SettableBeanProperty[] {
681                     constructCreatorProperty(ctxt, beanDesc, paramName, 0, param, injectId)
682             };
683             creators.addPropertyCreator(candidate.creator(), true, properties);
684             return;
685         }
686         _handleSingleArgumentCreator(creators, candidate.creator(), true, true);
687 
688         // one more thing: sever link to creator property, to avoid possible later
689         // problems with "unresolved" constructor property
690         if (paramDef != null) {
691             ((POJOPropertyBuilder) paramDef).removeConstructors();
692         }
693     }
694 
_checkIfCreatorPropertyBased(AnnotationIntrospector intr, AnnotatedWithParams creator, BeanPropertyDefinition propDef)695     private boolean _checkIfCreatorPropertyBased(AnnotationIntrospector intr,
696             AnnotatedWithParams creator, BeanPropertyDefinition propDef)
697     {
698         // If explicit name, or inject id, property-based
699         if (((propDef != null) && propDef.isExplicitlyNamed())
700                 || (intr.findInjectableValue(creator.getParameter(0)) != null)) {
701             return true;
702         }
703         if (propDef != null) {
704             // One more thing: if implicit name matches property with a getter
705             // or field, we'll consider it property-based as well
706             String implName = propDef.getName();
707             if (implName != null && !implName.isEmpty()) {
708                 if (propDef.couldSerialize()) {
709                     return true;
710                 }
711             }
712         }
713         // in absence of everything else, default to delegating
714         return false;
715     }
716 
_checkImplicitlyNamedConstructors(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker, AnnotationIntrospector intr, CreatorCollector creators, List<AnnotatedWithParams> implicitCtors)717     private void _checkImplicitlyNamedConstructors(DeserializationContext ctxt,
718             BeanDescription beanDesc, VisibilityChecker<?> vchecker,
719             AnnotationIntrospector intr, CreatorCollector creators,
720             List<AnnotatedWithParams> implicitCtors) throws JsonMappingException
721     {
722         AnnotatedWithParams found = null;
723         SettableBeanProperty[] foundProps = null;
724 
725         // Further checks: (a) must have names for all parameters, (b) only one visible
726         // Also, since earlier matching of properties and creators relied on existence of
727         // `@JsonCreator` (or equivalent) annotation, we need to do bit more re-inspection...
728 
729         main_loop:
730         for (AnnotatedWithParams ctor : implicitCtors) {
731             if (!vchecker.isCreatorVisible(ctor)) {
732                 continue;
733             }
734             // as per earlier notes, only end up here if no properties associated with creator
735             final int argCount = ctor.getParameterCount();
736             SettableBeanProperty[] properties = new SettableBeanProperty[argCount];
737             for (int i = 0; i < argCount; ++i) {
738                 final AnnotatedParameter param = ctor.getParameter(i);
739                 final PropertyName name = _findParamName(param, intr);
740 
741                 // must have name (implicit fine)
742                 if (name == null || name.isEmpty()) {
743                     continue main_loop;
744                 }
745                 properties[i] = constructCreatorProperty(ctxt, beanDesc, name, param.getIndex(),
746                         param, /*injectId*/ null);
747             }
748             if (found != null) { // only one allowed; but multiple not an error
749                 found = null;
750                 break;
751             }
752             found = ctor;
753             foundProps = properties;
754         }
755         // found one and only one visible? Ship it!
756         if (found != null) {
757             creators.addPropertyCreator(found, /*isCreator*/ false, foundProps);
758             BasicBeanDescription bbd = (BasicBeanDescription) beanDesc;
759             // Also: add properties, to keep error messages complete wrt known properties...
760             for (SettableBeanProperty prop : foundProps) {
761                 PropertyName pn = prop.getFullName();
762                 if (!bbd.hasProperty(pn)) {
763                     BeanPropertyDefinition newDef = SimpleBeanPropertyDefinition.construct(
764                             ctxt.getConfig(), prop.getMember(), pn);
765                     bbd.addProperty(newDef);
766                 }
767             }
768         }
769     }
770 
_addDeserializerFactoryMethods(DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker, AnnotationIntrospector intr, CreatorCollector creators, Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)771     protected void _addDeserializerFactoryMethods
772         (DeserializationContext ctxt, BeanDescription beanDesc, VisibilityChecker<?> vchecker,
773          AnnotationIntrospector intr, CreatorCollector creators,
774          Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)
775         throws JsonMappingException
776     {
777         List<CreatorCandidate> nonAnnotated = new LinkedList<>();
778         int explCount = 0;
779 
780         // 21-Sep-2017, tatu: First let's handle explicitly annotated ones
781         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
782             JsonCreator.Mode creatorMode = intr.findCreatorAnnotation(ctxt.getConfig(), factory);
783             final int argCount = factory.getParameterCount();
784             if (creatorMode == null) {
785                 // Only potentially accept 1-argument factory methods
786                 if ((argCount == 1) && vchecker.isCreatorVisible(factory)) {
787                     nonAnnotated.add(CreatorCandidate.construct(intr, factory, null));
788                 }
789                 continue;
790             }
791             if (creatorMode == Mode.DISABLED) {
792                 continue;
793             }
794 
795             // zero-arg method factory methods fine, as long as explicit
796             if (argCount == 0) {
797                 creators.setDefaultCreator(factory);
798                 continue;
799             }
800 
801             switch (creatorMode) {
802             case DELEGATING:
803                 _addExplicitDelegatingCreator(ctxt, beanDesc, creators,
804                         CreatorCandidate.construct(intr, factory, null));
805                 break;
806             case PROPERTIES:
807                 _addExplicitPropertyCreator(ctxt, beanDesc, creators,
808                         CreatorCandidate.construct(intr, factory, creatorParams.get(factory)));
809                 break;
810             case DEFAULT:
811             default:
812                 _addExplicitAnyCreator(ctxt, beanDesc, creators,
813                         CreatorCandidate.construct(intr, factory, creatorParams.get(factory)));
814                 break;
815             }
816             ++explCount;
817         }
818         // And only if and when those handled, consider potentially visible ones
819         if (explCount > 0) { // TODO: split method into two since we could have expl factories
820             return;
821         }
822         // And then implicitly found
823         for (CreatorCandidate candidate : nonAnnotated) {
824             final int argCount = candidate.paramCount();
825             AnnotatedWithParams factory = candidate.creator();
826             final BeanPropertyDefinition[] propDefs = creatorParams.get(factory);
827             // some single-arg factory methods (String, number) are auto-detected
828             if (argCount != 1) {
829                 continue; // 2 and more args? Must be explicit, handled earlier
830             }
831             BeanPropertyDefinition argDef = candidate.propertyDef(0);
832             boolean useProps = _checkIfCreatorPropertyBased(intr, factory, argDef);
833             if (!useProps) { // not property based but delegating
834                 /*boolean added=*/ _handleSingleArgumentCreator(creators,
835                         factory, false, vchecker.isCreatorVisible(factory));
836                 // 23-Sep-2016, tatu: [databind#1383]: Need to also sever link to avoid possible
837                 //    later problems with "unresolved" constructor property
838                 if (argDef != null) {
839                     ((POJOPropertyBuilder) argDef).removeConstructors();
840                 }
841                 continue;
842             }
843             AnnotatedParameter nonAnnotatedParam = null;
844             SettableBeanProperty[] properties = new SettableBeanProperty[argCount];
845             int implicitNameCount = 0;
846             int explicitNameCount = 0;
847             int injectCount = 0;
848 
849             for (int i = 0; i < argCount; ++i) {
850                 final AnnotatedParameter param = factory.getParameter(i);
851                 BeanPropertyDefinition propDef = (propDefs == null) ? null : propDefs[i];
852                 JacksonInject.Value injectable = intr.findInjectableValue(param);
853                 final PropertyName name = (propDef == null) ? null : propDef.getFullName();
854 
855                 if (propDef != null && propDef.isExplicitlyNamed()) {
856                     ++explicitNameCount;
857                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable);
858                     continue;
859                 }
860                 if (injectable != null) {
861                     ++injectCount;
862                     properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable);
863                     continue;
864                 }
865                 NameTransformer unwrapper = intr.findUnwrappingNameTransformer(param);
866                 if (unwrapper != null) {
867                     _reportUnwrappedCreatorProperty(ctxt, beanDesc, param);
868                     /*
869                     properties[i] = constructCreatorProperty(ctxt, beanDesc, UNWRAPPED_CREATOR_PARAM_NAME, i, param, null);
870                     ++implicitNameCount;
871                     */
872                     continue;
873                 }
874                 // One more thing: implicit names are ok iff ctor has creator annotation
875                 /*
876                 if (isCreator) {
877                     if (name != null && !name.isEmpty()) {
878                         ++implicitNameCount;
879                         properties[i] = constructCreatorProperty(ctxt, beanDesc, name, i, param, injectable);
880                         continue;
881                     }
882                 }
883                 */
884                 /* 25-Sep-2014, tatu: Actually, we may end up "losing" naming due to higher-priority constructor
885                  *  (see TestCreators#testConstructorCreator() test). And just to avoid running into that problem,
886                  *  let's add one more work around
887                  */
888                 /*
889                 PropertyName name2 = _findExplicitParamName(param, intr);
890                 if (name2 != null && !name2.isEmpty()) {
891                     // Hmmh. Ok, fine. So what are we to do with it... ?
892                     // For now... skip. May need to revisit this, should this become problematic
893                     continue main_loop;
894                 }
895                 */
896                 if (nonAnnotatedParam == null) {
897                     nonAnnotatedParam = param;
898                 }
899             }
900             final int namedCount = explicitNameCount + implicitNameCount;
901 
902             // Ok: if named or injectable, we have more work to do
903             if (explicitNameCount > 0 || injectCount > 0) {
904                 // simple case; everything covered:
905                 if ((namedCount + injectCount) == argCount) {
906                     creators.addPropertyCreator(factory, false, properties);
907                 } else if ((explicitNameCount == 0) && ((injectCount + 1) == argCount)) {
908                     // secondary: all but one injectable, one un-annotated (un-named)
909                     creators.addDelegatingCreator(factory, false, properties, 0);
910                 } else { // otherwise, epic fail
911                     ctxt.reportBadTypeDefinition(beanDesc,
912 "Argument #%d of factory method %s has no property name annotation; must have name when multiple-parameter constructor annotated as Creator",
913                     nonAnnotatedParam.getIndex(), factory);
914                 }
915             }
916         }
917     }
918 
_handleSingleArgumentCreator(CreatorCollector creators, AnnotatedWithParams ctor, boolean isCreator, boolean isVisible)919     protected boolean _handleSingleArgumentCreator(CreatorCollector creators,
920             AnnotatedWithParams ctor, boolean isCreator, boolean isVisible)
921     {
922         // otherwise either 'simple' number, String, or general delegate:
923         Class<?> type = ctor.getRawParameterType(0);
924         if (type == String.class || type == CLASS_CHAR_SEQUENCE) {
925             if (isCreator || isVisible) {
926                 creators.addStringCreator(ctor, isCreator);
927             }
928             return true;
929         }
930         if (type == int.class || type == Integer.class) {
931             if (isCreator || isVisible) {
932                 creators.addIntCreator(ctor, isCreator);
933             }
934             return true;
935         }
936         if (type == long.class || type == Long.class) {
937             if (isCreator || isVisible) {
938                 creators.addLongCreator(ctor, isCreator);
939             }
940             return true;
941         }
942         if (type == double.class || type == Double.class) {
943             if (isCreator || isVisible) {
944                 creators.addDoubleCreator(ctor, isCreator);
945             }
946             return true;
947         }
948         if (type == boolean.class || type == Boolean.class) {
949             if (isCreator || isVisible) {
950                 creators.addBooleanCreator(ctor, isCreator);
951             }
952             return true;
953         }
954         if (type == BigInteger.class) {
955             if (isCreator || isVisible) {
956                 creators.addBigIntegerCreator(ctor, isCreator);
957             }
958         }
959         if (type == BigDecimal.class) {
960             if (isCreator || isVisible) {
961                 creators.addBigDecimalCreator(ctor, isCreator);
962             }
963         }
964         // Delegating Creator ok iff it has @JsonCreator (etc)
965         if (isCreator) {
966             creators.addDelegatingCreator(ctor, isCreator, null, 0);
967             return true;
968         }
969         return false;
970     }
971 
972     // 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing
973     //   of unwrapped values through creator properties, so fail fast
_reportUnwrappedCreatorProperty(DeserializationContext ctxt, BeanDescription beanDesc, AnnotatedParameter param)974     protected void _reportUnwrappedCreatorProperty(DeserializationContext ctxt,
975             BeanDescription beanDesc, AnnotatedParameter param)
976         throws JsonMappingException
977     {
978         ctxt.reportBadDefinition(beanDesc.getType(), String.format(
979                 "Cannot define Creator parameter %d as `@JsonUnwrapped`: combination not yet supported",
980                 param.getIndex()));
981     }
982 
983     /**
984      * Method that will construct a property object that represents
985      * a logical property passed via Creator (constructor or static
986      * factory method)
987      */
constructCreatorProperty(DeserializationContext ctxt, BeanDescription beanDesc, PropertyName name, int index, AnnotatedParameter param, JacksonInject.Value injectable)988     protected SettableBeanProperty constructCreatorProperty(DeserializationContext ctxt,
989             BeanDescription beanDesc, PropertyName name, int index,
990             AnnotatedParameter param,
991             JacksonInject.Value injectable)
992         throws JsonMappingException
993     {
994         final DeserializationConfig config = ctxt.getConfig();
995         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
996         PropertyMetadata metadata;
997         {
998             if (intr == null) {
999                 metadata = PropertyMetadata.STD_REQUIRED_OR_OPTIONAL;
1000             } else {
1001                 Boolean b = intr.hasRequiredMarker(param);
1002                 String desc = intr.findPropertyDescription(param);
1003                 Integer idx = intr.findPropertyIndex(param);
1004                 String def = intr.findPropertyDefaultValue(param);
1005                 metadata = PropertyMetadata.construct(b, desc, idx, def);
1006             }
1007         }
1008         JavaType type = resolveMemberAndTypeAnnotations(ctxt, param, param.getType());
1009         BeanProperty.Std property = new BeanProperty.Std(name, type,
1010                 intr.findWrapperName(param), param, metadata);
1011         // Type deserializer: either comes from property (and already resolved)
1012         TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler();
1013         // or if not, based on type being referenced:
1014         if (typeDeser == null) {
1015             typeDeser = findTypeDeserializer(config, type);
1016         }
1017 
1018         // 22-Sep-2019, tatu: for [databind#2458] need more work on getting metadata
1019         //   about SetterInfo, mergeability
1020         metadata = _getSetterInfo(ctxt, property, metadata);
1021 
1022         // Note: contextualization of typeDeser _should_ occur in constructor of CreatorProperty
1023         // so it is not called directly here
1024         SettableBeanProperty prop = CreatorProperty.construct(name, type, property.getWrapperName(),
1025                 typeDeser, beanDesc.getClassAnnotations(), param, index, injectable,
1026                 metadata);
1027         JsonDeserializer<?> deser = findDeserializerFromAnnotation(ctxt, param);
1028         if (deser == null) {
1029             deser = type.getValueHandler();
1030         }
1031         if (deser != null) {
1032             // As per [databind#462] need to ensure we contextualize deserializer before passing it on
1033             deser = ctxt.handlePrimaryContextualization(deser, prop, type);
1034             prop = prop.withValueDeserializer(deser);
1035         }
1036         return prop;
1037     }
1038 
_findParamName(AnnotatedParameter param, AnnotationIntrospector intr)1039     private PropertyName _findParamName(AnnotatedParameter param, AnnotationIntrospector intr)
1040     {
1041         if (param != null && intr != null) {
1042             PropertyName name = intr.findNameForDeserialization(param);
1043             if (name != null) {
1044                 return name;
1045             }
1046             // 14-Apr-2014, tatu: Need to also consider possible implicit name
1047             //  (for JDK8, or via paranamer)
1048 
1049             String str = intr.findImplicitPropertyName(param);
1050             if (str != null && !str.isEmpty()) {
1051                 return PropertyName.construct(str);
1052             }
1053         }
1054         return null;
1055     }
1056 
1057     /**
1058      * Helper method copied from {@code POJOPropertyBuilder} since that won't be
1059      * applied to creator parameters
1060      *
1061      * @since 2.10
1062      */
_getSetterInfo(DeserializationContext ctxt, BeanProperty prop, PropertyMetadata metadata)1063     protected PropertyMetadata _getSetterInfo(DeserializationContext ctxt,
1064             BeanProperty prop, PropertyMetadata metadata)
1065     {
1066         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
1067         final DeserializationConfig config = ctxt.getConfig();
1068 
1069         boolean needMerge = true;
1070         Nulls valueNulls = null;
1071         Nulls contentNulls = null;
1072 
1073         // NOTE: compared to `POJOPropertyBuilder`, we only have access to creator
1074         // parameter, not other accessors, so code bit simpler
1075         AnnotatedMember prim = prop.getMember();
1076 
1077         if (prim != null) {
1078             // Ok, first: does property itself have something to say?
1079             if (intr != null) {
1080                 JsonSetter.Value setterInfo = intr.findSetterInfo(prim);
1081                 if (setterInfo != null) {
1082                     valueNulls = setterInfo.nonDefaultValueNulls();
1083                     contentNulls = setterInfo.nonDefaultContentNulls();
1084                 }
1085             }
1086             // If not, config override?
1087             // 25-Oct-2016, tatu: Either this, or type of accessor...
1088             if (needMerge || (valueNulls == null) || (contentNulls == null)) {
1089                 ConfigOverride co = config.getConfigOverride(prop.getType().getRawClass());
1090                 JsonSetter.Value setterInfo = co.getSetterInfo();
1091                 if (setterInfo != null) {
1092                     if (valueNulls == null) {
1093                         valueNulls = setterInfo.nonDefaultValueNulls();
1094                     }
1095                     if (contentNulls == null) {
1096                         contentNulls = setterInfo.nonDefaultContentNulls();
1097                     }
1098                 }
1099             }
1100         }
1101         if (needMerge || (valueNulls == null) || (contentNulls == null)) {
1102             JsonSetter.Value setterInfo = config.getDefaultSetterInfo();
1103             if (valueNulls == null) {
1104                 valueNulls = setterInfo.nonDefaultValueNulls();
1105             }
1106             if (contentNulls == null) {
1107                 contentNulls = setterInfo.nonDefaultContentNulls();
1108             }
1109         }
1110         if ((valueNulls != null) || (contentNulls != null)) {
1111             metadata = metadata.withNulls(valueNulls, contentNulls);
1112         }
1113         return metadata;
1114     }
1115 
1116     /*
1117     /**********************************************************
1118     /* DeserializerFactory impl: array deserializers
1119     /**********************************************************
1120      */
1121 
1122     @Override
createArrayDeserializer(DeserializationContext ctxt, ArrayType type, final BeanDescription beanDesc)1123     public JsonDeserializer<?> createArrayDeserializer(DeserializationContext ctxt,
1124             ArrayType type, final BeanDescription beanDesc)
1125         throws JsonMappingException
1126     {
1127         final DeserializationConfig config = ctxt.getConfig();
1128         JavaType elemType = type.getContentType();
1129 
1130         // Very first thing: is deserializer hard-coded for elements?
1131         JsonDeserializer<Object> contentDeser = elemType.getValueHandler();
1132         // Then optional type info: if type has been resolved, we may already know type deserializer:
1133         TypeDeserializer elemTypeDeser = elemType.getTypeHandler();
1134         // but if not, may still be possible to find:
1135         if (elemTypeDeser == null) {
1136             elemTypeDeser = findTypeDeserializer(config, elemType);
1137         }
1138         // 23-Nov-2010, tatu: Custom array deserializer?
1139         JsonDeserializer<?>  deser = _findCustomArrayDeserializer(type,
1140                 config, beanDesc, elemTypeDeser, contentDeser);
1141         if (deser == null) {
1142             if (contentDeser == null) {
1143                 Class<?> raw = elemType.getRawClass();
1144                 if (elemType.isPrimitive()) {
1145                     return PrimitiveArrayDeserializers.forType(raw);
1146                 }
1147                 if (raw == String.class) {
1148                     return StringArrayDeserializer.instance;
1149                 }
1150             }
1151             deser = new ObjectArrayDeserializer(type, contentDeser, elemTypeDeser);
1152         }
1153         // and then new with 2.2: ability to post-process it too (databind#120)
1154         if (_factoryConfig.hasDeserializerModifiers()) {
1155             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1156                 deser = mod.modifyArrayDeserializer(config, type, beanDesc, deser);
1157             }
1158         }
1159         return deser;
1160     }
1161 
1162     /*
1163     /**********************************************************************
1164     /* DeserializerFactory impl: Collection(-like) deserializers
1165     /**********************************************************************
1166      */
1167 
1168     @Override
createCollectionDeserializer(DeserializationContext ctxt, CollectionType type, BeanDescription beanDesc)1169     public JsonDeserializer<?> createCollectionDeserializer(DeserializationContext ctxt,
1170             CollectionType type, BeanDescription beanDesc)
1171         throws JsonMappingException
1172     {
1173         JavaType contentType = type.getContentType();
1174         // Very first thing: is deserializer hard-coded for elements?
1175         JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
1176         final DeserializationConfig config = ctxt.getConfig();
1177 
1178         // Then optional type info: if type has been resolved, we may already know type deserializer:
1179         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
1180         // but if not, may still be possible to find:
1181         if (contentTypeDeser == null) {
1182             contentTypeDeser = findTypeDeserializer(config, contentType);
1183         }
1184         // 23-Nov-2010, tatu: Custom deserializer?
1185         JsonDeserializer<?> deser = _findCustomCollectionDeserializer(type,
1186                 config, beanDesc, contentTypeDeser, contentDeser);
1187         if (deser == null) {
1188             Class<?> collectionClass = type.getRawClass();
1189             if (contentDeser == null) { // not defined by annotation
1190                 // One special type: EnumSet:
1191                 if (EnumSet.class.isAssignableFrom(collectionClass)) {
1192                     deser = new EnumSetDeserializer(contentType, null);
1193                 }
1194             }
1195         }
1196 
1197         /* One twist: if we are being asked to instantiate an interface or
1198          * abstract Collection, we need to either find something that implements
1199          * the thing, or give up.
1200          *
1201          * Note that we do NOT try to guess based on secondary interfaces
1202          * here; that would probably not work correctly since casts would
1203          * fail later on (as the primary type is not the interface we'd
1204          * be implementing)
1205          */
1206         if (deser == null) {
1207             if (type.isInterface() || type.isAbstract()) {
1208                 CollectionType implType = _mapAbstractCollectionType(type, config);
1209                 if (implType == null) {
1210                     // [databind#292]: Actually, may be fine, but only if polymorphich deser enabled
1211                     if (type.getTypeHandler() == null) {
1212                         throw new IllegalArgumentException("Cannot find a deserializer for non-concrete Collection type "+type);
1213                     }
1214                     deser = AbstractDeserializer.constructForNonPOJO(beanDesc);
1215                 } else {
1216                     type = implType;
1217                     // But if so, also need to re-check creators...
1218                     beanDesc = config.introspectForCreation(type);
1219                 }
1220             }
1221             if (deser == null) {
1222                 ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
1223                 if (!inst.canCreateUsingDefault()) {
1224                     // [databind#161]: No default constructor for ArrayBlockingQueue...
1225                     if (type.hasRawClass(ArrayBlockingQueue.class)) {
1226                         return new ArrayBlockingQueueDeserializer(type, contentDeser, contentTypeDeser, inst);
1227                     }
1228                     // 10-Jan-2017, tatu: `java.util.Collections` types need help:
1229                     deser = JavaUtilCollectionsDeserializers.findForCollection(ctxt, type);
1230                     if (deser != null) {
1231                         return deser;
1232                     }
1233                 }
1234                 // Can use more optimal deserializer if content type is String, so:
1235                 if (contentType.hasRawClass(String.class)) {
1236                     // no value type deserializer because Strings are one of natural/native types:
1237                     deser = new StringCollectionDeserializer(type, contentDeser, inst);
1238                 } else {
1239                     deser = new CollectionDeserializer(type, contentDeser, contentTypeDeser, inst);
1240                 }
1241             }
1242         }
1243         // allow post-processing it too
1244         if (_factoryConfig.hasDeserializerModifiers()) {
1245             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1246                 deser = mod.modifyCollectionDeserializer(config, type, beanDesc, deser);
1247             }
1248         }
1249         return deser;
1250     }
1251 
_mapAbstractCollectionType(JavaType type, DeserializationConfig config)1252     protected CollectionType _mapAbstractCollectionType(JavaType type, DeserializationConfig config)
1253     {
1254         final Class<?> collectionClass = ContainerDefaultMappings.findCollectionFallback(type);
1255         if (collectionClass != null) {
1256             return (CollectionType) config.getTypeFactory()
1257                     .constructSpecializedType(type, collectionClass, true);
1258         }
1259         return null;
1260     }
1261 
1262     // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code
1263     @Override
createCollectionLikeDeserializer(DeserializationContext ctxt, CollectionLikeType type, final BeanDescription beanDesc)1264     public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationContext ctxt,
1265             CollectionLikeType type, final BeanDescription beanDesc)
1266         throws JsonMappingException
1267     {
1268         JavaType contentType = type.getContentType();
1269         // Very first thing: is deserializer hard-coded for elements?
1270         JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
1271         final DeserializationConfig config = ctxt.getConfig();
1272 
1273         // Then optional type info (1.5): if type has been resolved, we may already know type deserializer:
1274         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
1275         // but if not, may still be possible to find:
1276         if (contentTypeDeser == null) {
1277             contentTypeDeser = findTypeDeserializer(config, contentType);
1278         }
1279         JsonDeserializer<?> deser = _findCustomCollectionLikeDeserializer(type, config, beanDesc,
1280                 contentTypeDeser, contentDeser);
1281         if (deser != null) {
1282             // and then new with 2.2: ability to post-process it too (Issue#120)
1283             if (_factoryConfig.hasDeserializerModifiers()) {
1284                 for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1285                     deser = mod.modifyCollectionLikeDeserializer(config, type, beanDesc, deser);
1286                 }
1287             }
1288         }
1289         return deser;
1290     }
1291 
1292     /*
1293     /**********************************************************
1294     /* DeserializerFactory impl: Map(-like) deserializers
1295     /**********************************************************
1296      */
1297 
1298     @Override
createMapDeserializer(DeserializationContext ctxt, MapType type, BeanDescription beanDesc)1299     public JsonDeserializer<?> createMapDeserializer(DeserializationContext ctxt,
1300             MapType type, BeanDescription beanDesc)
1301         throws JsonMappingException
1302     {
1303         final DeserializationConfig config = ctxt.getConfig();
1304         JavaType keyType = type.getKeyType();
1305         JavaType contentType = type.getContentType();
1306 
1307         // First: is there annotation-specified deserializer for values?
1308         @SuppressWarnings("unchecked")
1309         JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
1310 
1311         // Ok: need a key deserializer (null indicates 'default' here)
1312         KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler();
1313         // Then optional type info; either attached to type, or resolved separately:
1314         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
1315         // but if not, may still be possible to find:
1316         if (contentTypeDeser == null) {
1317             contentTypeDeser = findTypeDeserializer(config, contentType);
1318         }
1319 
1320         // 23-Nov-2010, tatu: Custom deserializer?
1321         JsonDeserializer<?> deser = _findCustomMapDeserializer(type, config, beanDesc,
1322                 keyDes, contentTypeDeser, contentDeser);
1323 
1324         if (deser == null) {
1325             // Value handling is identical for all, but EnumMap requires special handling for keys
1326             Class<?> mapClass = type.getRawClass();
1327             if (EnumMap.class.isAssignableFrom(mapClass)) {
1328                 ValueInstantiator inst;
1329 
1330                 // 06-Mar-2017, tatu: Should only need to check ValueInstantiator for
1331                 //    custom sub-classes, see [databind#1544]
1332                 if (mapClass == EnumMap.class) {
1333                     inst = null;
1334                 } else {
1335                     inst = findValueInstantiator(ctxt, beanDesc);
1336                 }
1337                 if (!keyType.isEnumImplType()) {
1338                     throw new IllegalArgumentException("Cannot construct EnumMap; generic (key) type not available");
1339                 }
1340                 deser = new EnumMapDeserializer(type, inst, null,
1341                         contentDeser, contentTypeDeser, null);
1342             }
1343 
1344             // Otherwise, generic handler works ok.
1345 
1346             /* But there is one more twist: if we are being asked to instantiate
1347              * an interface or abstract Map, we need to either find something
1348              * that implements the thing, or give up.
1349              *
1350              * Note that we do NOT try to guess based on secondary interfaces
1351              * here; that would probably not work correctly since casts would
1352              * fail later on (as the primary type is not the interface we'd
1353              * be implementing)
1354              */
1355             if (deser == null) {
1356                 if (type.isInterface() || type.isAbstract()) {
1357                     MapType fallback = _mapAbstractMapType(type, config);
1358                     if (fallback != null) {
1359                         type = (MapType) fallback;
1360                         mapClass = type.getRawClass();
1361                         // But if so, also need to re-check creators...
1362                         beanDesc = config.introspectForCreation(type);
1363                     } else {
1364                         // [databind#292]: Actually, may be fine, but only if polymorphic deser enabled
1365                         if (type.getTypeHandler() == null) {
1366                             throw new IllegalArgumentException("Cannot find a deserializer for non-concrete Map type "+type);
1367                         }
1368                         deser = AbstractDeserializer.constructForNonPOJO(beanDesc);
1369                     }
1370                 } else {
1371                     // 10-Jan-2017, tatu: `java.util.Collections` types need help:
1372                     deser = JavaUtilCollectionsDeserializers.findForMap(ctxt, type);
1373                     if (deser != null) {
1374                         return deser;
1375                     }
1376                 }
1377                 if (deser == null) {
1378                     ValueInstantiator inst = findValueInstantiator(ctxt, beanDesc);
1379                     // 01-May-2016, tatu: Which base type to use here gets tricky, since
1380                     //   most often it ought to be `Map` or `EnumMap`, but due to abstract
1381                     //   mapping it will more likely be concrete type like `HashMap`.
1382                     //   So, for time being, just pass `Map.class`
1383                     MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser);
1384                     JsonIgnoreProperties.Value ignorals = config.getDefaultPropertyIgnorals(Map.class,
1385                             beanDesc.getClassInfo());
1386                     Set<String> ignored = (ignorals == null) ? null
1387                             : ignorals.findIgnoredForDeserialization();
1388                     md.setIgnorableProperties(ignored);
1389                     JsonIncludeProperties.Value inclusions = config.getDefaultPropertyInclusions(Map.class,
1390                             beanDesc.getClassInfo());
1391                     Set<String> included = inclusions == null ? null : inclusions.getIncluded();
1392                     md.setIncludableProperties(included);
1393                     deser = md;
1394                 }
1395             }
1396         }
1397         if (_factoryConfig.hasDeserializerModifiers()) {
1398             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1399                 deser = mod.modifyMapDeserializer(config, type, beanDesc, deser);
1400             }
1401         }
1402         return deser;
1403     }
1404 
_mapAbstractMapType(JavaType type, DeserializationConfig config)1405     protected MapType _mapAbstractMapType(JavaType type, DeserializationConfig config)
1406     {
1407         final Class<?> mapClass = ContainerDefaultMappings.findMapFallback(type);
1408         if (mapClass != null) {
1409             return (MapType) config.getTypeFactory()
1410                     .constructSpecializedType(type, mapClass, true);
1411         }
1412         return null;
1413     }
1414 
1415     // Copied almost verbatim from "createMapDeserializer" -- should try to share more code
1416     @Override
createMapLikeDeserializer(DeserializationContext ctxt, MapLikeType type, final BeanDescription beanDesc)1417     public JsonDeserializer<?> createMapLikeDeserializer(DeserializationContext ctxt,
1418             MapLikeType type, final BeanDescription beanDesc)
1419         throws JsonMappingException
1420     {
1421         JavaType keyType = type.getKeyType();
1422         JavaType contentType = type.getContentType();
1423         final DeserializationConfig config = ctxt.getConfig();
1424 
1425         // First: is there annotation-specified deserializer for values?
1426         @SuppressWarnings("unchecked")
1427         JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler();
1428 
1429         // Ok: need a key deserializer (null indicates 'default' here)
1430         KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler();
1431         /* !!! 24-Jan-2012, tatu: NOTE: impls MUST use resolve() to find key deserializer!
1432         if (keyDes == null) {
1433             keyDes = p.findKeyDeserializer(config, keyType, property);
1434         }
1435         */
1436         // Then optional type info (1.5); either attached to type, or resolve separately:
1437         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
1438         // but if not, may still be possible to find:
1439         if (contentTypeDeser == null) {
1440             contentTypeDeser = findTypeDeserializer(config, contentType);
1441         }
1442         JsonDeserializer<?> deser = _findCustomMapLikeDeserializer(type, config,
1443                 beanDesc, keyDes, contentTypeDeser, contentDeser);
1444         if (deser != null) {
1445             // and then new with 2.2: ability to post-process it too (Issue#120)
1446             if (_factoryConfig.hasDeserializerModifiers()) {
1447                 for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1448                     deser = mod.modifyMapLikeDeserializer(config, type, beanDesc, deser);
1449                 }
1450             }
1451         }
1452         return deser;
1453     }
1454 
1455     /*
1456     /**********************************************************
1457     /* DeserializerFactory impl: other types
1458     /**********************************************************
1459      */
1460 
1461     /**
1462      * Factory method for constructing serializers of {@link Enum} types.
1463      */
1464     @Override
createEnumDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc)1465     public JsonDeserializer<?> createEnumDeserializer(DeserializationContext ctxt,
1466             JavaType type, BeanDescription beanDesc)
1467         throws JsonMappingException
1468     {
1469         final DeserializationConfig config = ctxt.getConfig();
1470         final Class<?> enumClass = type.getRawClass();
1471         // 23-Nov-2010, tatu: Custom deserializer?
1472         JsonDeserializer<?> deser = _findCustomEnumDeserializer(enumClass, config, beanDesc);
1473 
1474         if (deser == null) {
1475             // 12-Feb-2020, tatu: while we can't really create real deserializer for `Enum.class`,
1476             //    it is necessary to allow it in one specific case: see [databind#2605] for details
1477             //    but basically it can be used as polymorphic base.
1478             //    We could check `type.getTypeHandler()` to look for that case but seems like we
1479             //    may as well simply create placeholder (AbstractDeserializer) regardless
1480             if (enumClass == Enum.class) {
1481                 return AbstractDeserializer.constructForNonPOJO(beanDesc);
1482             }
1483 
1484             ValueInstantiator valueInstantiator = _constructDefaultValueInstantiator(ctxt, beanDesc);
1485             SettableBeanProperty[] creatorProps = (valueInstantiator == null) ? null
1486                     : valueInstantiator.getFromObjectArguments(ctxt.getConfig());
1487             // May have @JsonCreator for static factory method:
1488             for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
1489                 if (_hasCreatorAnnotation(ctxt, factory)) {
1490                     if (factory.getParameterCount() == 0) { // [databind#960]
1491                         deser = EnumDeserializer.deserializerForNoArgsCreator(config, enumClass, factory);
1492                         break;
1493                     }
1494                     Class<?> returnType = factory.getRawReturnType();
1495                     // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
1496                     if (!returnType.isAssignableFrom(enumClass)) {
1497                         ctxt.reportBadDefinition(type, String.format(
1498 "Invalid `@JsonCreator` annotated Enum factory method [%s]: needs to return compatible type",
1499 factory.toString()));
1500                     }
1501                     deser = EnumDeserializer.deserializerForCreator(config, enumClass, factory, valueInstantiator, creatorProps);
1502                     break;
1503                 }
1504             }
1505 
1506             // Need to consider @JsonValue if one found
1507             if (deser == null) {
1508                 deser = new EnumDeserializer(constructEnumResolver(enumClass,
1509                         config, beanDesc.findJsonValueAccessor()),
1510                         config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS));
1511             }
1512         }
1513 
1514         // and then post-process it too
1515         if (_factoryConfig.hasDeserializerModifiers()) {
1516             for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1517                 deser = mod.modifyEnumDeserializer(config, type, beanDesc, deser);
1518             }
1519         }
1520         return deser;
1521     }
1522 
1523     @Override
createTreeDeserializer(DeserializationConfig config, JavaType nodeType, BeanDescription beanDesc)1524     public JsonDeserializer<?> createTreeDeserializer(DeserializationConfig config,
1525             JavaType nodeType, BeanDescription beanDesc)
1526         throws JsonMappingException
1527     {
1528         @SuppressWarnings("unchecked")
1529         Class<? extends JsonNode> nodeClass = (Class<? extends JsonNode>) nodeType.getRawClass();
1530         // 23-Nov-2010, tatu: Custom deserializer?
1531         JsonDeserializer<?> custom = _findCustomTreeNodeDeserializer(nodeClass, config,
1532                 beanDesc);
1533         if (custom != null) {
1534             return custom;
1535         }
1536         return JsonNodeDeserializer.getDeserializer(nodeClass);
1537     }
1538 
1539     @Override
createReferenceDeserializer(DeserializationContext ctxt, ReferenceType type, BeanDescription beanDesc)1540     public JsonDeserializer<?> createReferenceDeserializer(DeserializationContext ctxt,
1541             ReferenceType type, BeanDescription beanDesc)
1542         throws JsonMappingException
1543     {
1544         JavaType contentType = type.getContentType();
1545         // Very first thing: is deserializer hard-coded for elements?
1546         JsonDeserializer<Object> contentDeser = contentType.getValueHandler();
1547         final DeserializationConfig config = ctxt.getConfig();
1548         // Then optional type info: if type has been resolved, we may already know type deserializer:
1549         TypeDeserializer contentTypeDeser = contentType.getTypeHandler();
1550         if (contentTypeDeser == null) { // or if not, may be able to find:
1551             contentTypeDeser = findTypeDeserializer(config, contentType);
1552         }
1553         JsonDeserializer<?> deser = _findCustomReferenceDeserializer(type, config, beanDesc,
1554                 contentTypeDeser, contentDeser);
1555 
1556         if (deser == null) {
1557             // Just one referential type as of JDK 1.7 / Java 7: AtomicReference (Java 8 adds Optional)
1558             if (type.isTypeOrSubTypeOf(AtomicReference.class)) {
1559                 Class<?> rawType = type.getRawClass();
1560                 ValueInstantiator inst;
1561                 if (rawType == AtomicReference.class) {
1562                     inst = null;
1563                 } else {
1564                     /* 23-Oct-2016, tatu: Note that subtypes are probably not supportable
1565                      *    without either forcing merging (to avoid having to create instance)
1566                      *    or something else...
1567                      */
1568                     inst = findValueInstantiator(ctxt, beanDesc);
1569                 }
1570                 return new AtomicReferenceDeserializer(type, inst, contentTypeDeser, contentDeser);
1571             }
1572         }
1573         if (deser != null) {
1574             // and then post-process
1575             if (_factoryConfig.hasDeserializerModifiers()) {
1576                 for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1577                     deser = mod.modifyReferenceDeserializer(config, type, beanDesc, deser);
1578                 }
1579             }
1580         }
1581         return deser;
1582     }
1583 
1584     /*
1585     /**********************************************************
1586     /* DeserializerFactory impl (partial): type deserializers
1587     /**********************************************************
1588      */
1589 
1590     @Override
findTypeDeserializer(DeserializationConfig config, JavaType baseType)1591     public TypeDeserializer findTypeDeserializer(DeserializationConfig config,
1592             JavaType baseType)
1593         throws JsonMappingException
1594     {
1595         BeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass());
1596         AnnotatedClass ac = bean.getClassInfo();
1597         AnnotationIntrospector ai = config.getAnnotationIntrospector();
1598         TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType);
1599 
1600         // Ok: if there is no explicit type info handler, we may want to
1601         // use a default. If so, config object knows what to use.
1602         Collection<NamedType> subtypes = null;
1603         if (b == null) {
1604             b = config.getDefaultTyper(baseType);
1605             if (b == null) {
1606                 return null;
1607             }
1608         } else {
1609             subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId(config, ac);
1610         }
1611         // May need to figure out default implementation, if none found yet
1612         // (note: check for abstract type is not 100% mandatory, more of an optimization)
1613         if ((b.getDefaultImpl() == null) && baseType.isAbstract()) {
1614             JavaType defaultType = mapAbstractType(config, baseType);
1615             if ((defaultType != null) && !defaultType.hasRawClass(baseType.getRawClass())) {
1616                 b = b.defaultImpl(defaultType.getRawClass());
1617             }
1618         }
1619         // 05-Apt-2018, tatu: Since we get non-mapping exception due to various limitations,
1620         //    map to better type here
1621         try {
1622             return b.buildTypeDeserializer(config, baseType, subtypes);
1623         } catch (IllegalArgumentException e0) {
1624             InvalidDefinitionException e = InvalidDefinitionException.from((JsonParser) null,
1625                     ClassUtil.exceptionMessage(e0), baseType);
1626             e.initCause(e0);
1627             throw e;
1628         }
1629     }
1630 
1631     /**
1632      * Overridable method called after checking all other types.
1633      *
1634      * @since 2.2
1635      */
findOptionalStdDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc)1636     protected JsonDeserializer<?> findOptionalStdDeserializer(DeserializationContext ctxt,
1637             JavaType type, BeanDescription beanDesc)
1638         throws JsonMappingException
1639     {
1640         return OptionalHandlerFactory.instance.findDeserializer(type, ctxt.getConfig(), beanDesc);
1641     }
1642 
1643     /*
1644     /**********************************************************
1645     /* DeserializerFactory impl (partial): key deserializers
1646     /**********************************************************
1647      */
1648 
1649     @Override
createKeyDeserializer(DeserializationContext ctxt, JavaType type)1650     public KeyDeserializer createKeyDeserializer(DeserializationContext ctxt,
1651             JavaType type)
1652         throws JsonMappingException
1653     {
1654         final DeserializationConfig config = ctxt.getConfig();
1655         BeanDescription beanDesc = null;
1656         KeyDeserializer deser = null;
1657         if (_factoryConfig.hasKeyDeserializers()) {
1658             beanDesc = config.introspectClassAnnotations(type);
1659             for (KeyDeserializers d  : _factoryConfig.keyDeserializers()) {
1660                 deser = d.findKeyDeserializer(type, config, beanDesc);
1661                 if (deser != null) {
1662                     break;
1663                 }
1664             }
1665         }
1666 
1667         // the only non-standard thing is this:
1668         if (deser == null) {
1669             // [databind#2452]: Support `@JsonDeserialize(keyUsing = ...)`
1670             if (beanDesc == null) {
1671                 beanDesc = config.introspectClassAnnotations(type.getRawClass());
1672             }
1673             deser = findKeyDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo());
1674             if (deser == null) {
1675                 if (type.isEnumType()) {
1676                     deser = _createEnumKeyDeserializer(ctxt, type);
1677                 } else {
1678                     deser = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type);
1679                 }
1680             }
1681         }
1682         // and then post-processing
1683         if (deser != null) {
1684             if (_factoryConfig.hasDeserializerModifiers()) {
1685                 for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) {
1686                     deser = mod.modifyKeyDeserializer(config, type, deser);
1687                 }
1688             }
1689         }
1690         return deser;
1691     }
1692 
_createEnumKeyDeserializer(DeserializationContext ctxt, JavaType type)1693     private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt,
1694             JavaType type)
1695         throws JsonMappingException
1696     {
1697         final DeserializationConfig config = ctxt.getConfig();
1698         Class<?> enumClass = type.getRawClass();
1699 
1700         BeanDescription beanDesc = config.introspect(type);
1701         // 24-Sep-2015, bim: a key deserializer is the preferred thing.
1702         KeyDeserializer des = findKeyDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo());
1703         if (des != null) {
1704             return des;
1705         } else {
1706             // 24-Sep-2015, bim: if no key deser, look for enum deserializer first, then a plain deser.
1707             JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass, config, beanDesc);
1708             if (custom != null) {
1709                 return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, custom);
1710             }
1711             JsonDeserializer<?> valueDesForKey = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo());
1712             if (valueDesForKey != null) {
1713                 return StdKeyDeserializers.constructDelegatingKeyDeserializer(config, type, valueDesForKey);
1714             }
1715         }
1716         EnumResolver enumRes = constructEnumResolver(enumClass, config, beanDesc.findJsonValueAccessor());
1717 
1718         // May have @JsonCreator for static factory method
1719         for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) {
1720             if (_hasCreatorAnnotation(ctxt, factory)) {
1721                 int argCount = factory.getParameterCount();
1722                 if (argCount == 1) {
1723                     Class<?> returnType = factory.getRawReturnType();
1724                     // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?)
1725                     if (returnType.isAssignableFrom(enumClass)) {
1726                         // note: mostly copied from 'EnumDeserializer.deserializerForCreator(...)'
1727                         if (factory.getRawParameterType(0) != String.class) {
1728                             // [databind#2725]: Should not error out because (1) there may be good creator
1729                             //   method and (2) this method may be valid for "regular" enum value deserialization
1730                             // (leaving aside potential for multiple conflicting creators)
1731 //                            throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory+") not suitable, must be java.lang.String");
1732                             continue;
1733                         }
1734                         if (config.canOverrideAccessModifiers()) {
1735                             ClassUtil.checkAndFixAccess(factory.getMember(),
1736                                     ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
1737                         }
1738                         return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory);
1739                     }
1740                 }
1741                 throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type "
1742                         +enumClass.getName()+")");
1743             }
1744         }
1745         // Also, need to consider @JsonValue, if one found
1746         return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes);
1747     }
1748 
1749     /*
1750     /**********************************************************
1751     /* DeserializerFactory impl: checking explicitly registered desers
1752     /**********************************************************
1753      */
1754 
1755     @Override
hasExplicitDeserializerFor(DeserializationConfig config, Class<?> valueType)1756     public boolean hasExplicitDeserializerFor(DeserializationConfig config,
1757             Class<?> valueType)
1758     {
1759         // First things first: unpeel Array types as the element type is
1760         // what we are interested in -- this because we will always support array
1761         // types via composition, and since array types are JDK provided (and hence
1762         // can not be custom or customized).
1763         while (valueType.isArray()) {
1764             valueType = valueType.getComponentType();
1765         }
1766 
1767         // Yes, we handle all Enum types
1768         if (Enum.class.isAssignableFrom(valueType)) {
1769             return true;
1770         }
1771         // Numbers?
1772         final String clsName = valueType.getName();
1773         if (clsName.startsWith("java.")) {
1774             if (Collection.class.isAssignableFrom(valueType)) {
1775                 return true;
1776             }
1777             if (Map.class.isAssignableFrom(valueType)) {
1778                 return true;
1779             }
1780             if (Number.class.isAssignableFrom(valueType)) {
1781                 return NumberDeserializers.find(valueType, clsName) != null;
1782             }
1783             if (JdkDeserializers.hasDeserializerFor(valueType)
1784                     || (valueType == CLASS_STRING)
1785                     || (valueType == Boolean.class)
1786                     || (valueType == EnumMap.class)
1787                     || (valueType == AtomicReference.class)
1788                     ) {
1789                 return true;
1790             }
1791             if (DateDeserializers.hasDeserializerFor(valueType)) {
1792                 return true;
1793             }
1794         } else if (clsName.startsWith("com.fasterxml.")) {
1795             return JsonNode.class.isAssignableFrom(valueType)
1796                    || (valueType == TokenBuffer.class);
1797         } else {
1798             return OptionalHandlerFactory.instance.hasDeserializerFor(valueType);
1799         }
1800         return false;
1801     }
1802 
1803     /*
1804     /**********************************************************
1805     /* Extended API
1806     /**********************************************************
1807      */
1808 
1809     /**
1810      * Method called to create a type information deserializer for values of
1811      * given non-container property, if one is needed.
1812      * If not needed (no polymorphic handling configured for property), should return null.
1813      *<p>
1814      * Note that this method is only called for non-container bean properties,
1815      * and not for values in container types or root values (or container properties)
1816      *
1817      * @param baseType Declared base type of the value to deserializer (actual
1818      *    deserializer type will be this type or its subtype)
1819      *
1820      * @return Type deserializer to use for given base type, if one is needed; null if not.
1821      */
findPropertyTypeDeserializer(DeserializationConfig config, JavaType baseType, AnnotatedMember annotated)1822     public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig config,
1823             JavaType baseType, AnnotatedMember annotated)
1824         throws JsonMappingException
1825     {
1826         AnnotationIntrospector ai = config.getAnnotationIntrospector();
1827         TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, annotated, baseType);
1828         // Defaulting: if no annotations on member, check value class
1829         if (b == null) {
1830             return findTypeDeserializer(config, baseType);
1831         }
1832         // but if annotations found, may need to resolve subtypes:
1833         Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId(
1834                 config, annotated, baseType);
1835         try {
1836             return b.buildTypeDeserializer(config, baseType, subtypes);
1837         } catch (IllegalArgumentException e0) {
1838             InvalidDefinitionException e = InvalidDefinitionException.from((JsonParser) null,
1839                     ClassUtil.exceptionMessage(e0), baseType);
1840             e.initCause(e0);
1841             throw e;
1842         }
1843     }
1844 
1845     /**
1846      * Method called to find and create a type information deserializer for values of
1847      * given container (list, array, map) property, if one is needed.
1848      * If not needed (no polymorphic handling configured for property), should return null.
1849      *<p>
1850      * Note that this method is only called for container bean properties,
1851      * and not for values in container types or root values (or non-container properties)
1852      *
1853      * @param containerType Type of property; must be a container type
1854      * @param propertyEntity Field or method that contains container property
1855      */
findPropertyContentTypeDeserializer(DeserializationConfig config, JavaType containerType, AnnotatedMember propertyEntity)1856     public TypeDeserializer findPropertyContentTypeDeserializer(DeserializationConfig config,
1857             JavaType containerType, AnnotatedMember propertyEntity)
1858         throws JsonMappingException
1859     {
1860         AnnotationIntrospector ai = config.getAnnotationIntrospector();
1861         TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType);
1862         JavaType contentType = containerType.getContentType();
1863         // Defaulting: if no annotations on member, check class
1864         if (b == null) {
1865             return findTypeDeserializer(config, contentType);
1866         }
1867         // but if annotations found, may need to resolve subtypes:
1868         Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypesByTypeId(
1869                 config, propertyEntity, contentType);
1870         return b.buildTypeDeserializer(config, contentType, subtypes);
1871     }
1872 
1873     /**
1874      * Helper method called to find one of default serializers for "well-known"
1875      * platform types: JDK-provided types, and small number of public Jackson
1876      * API types.
1877      *
1878      * @since 2.2
1879      */
findDefaultDeserializer(DeserializationContext ctxt, JavaType type, BeanDescription beanDesc)1880     public JsonDeserializer<?> findDefaultDeserializer(DeserializationContext ctxt,
1881             JavaType type, BeanDescription beanDesc)
1882         throws JsonMappingException
1883     {
1884         Class<?> rawType = type.getRawClass();
1885         // Object ("untyped"), and as of 2.10 (see [databind#2115]), `java.io.Serializable`
1886         if ((rawType == CLASS_OBJECT) || (rawType == CLASS_SERIALIZABLE)) {
1887             // 11-Feb-2015, tatu: As per [databind#700] need to be careful wrt non-default Map, List.
1888             DeserializationConfig config = ctxt.getConfig();
1889             JavaType lt, mt;
1890 
1891             if (_factoryConfig.hasAbstractTypeResolvers()) {
1892                 lt = _findRemappedType(config, List.class);
1893                 mt = _findRemappedType(config, Map.class);
1894             } else {
1895                 lt = mt = null;
1896             }
1897             return new UntypedObjectDeserializer(lt, mt);
1898         }
1899         // String and equivalents
1900         if (rawType == CLASS_STRING || rawType == CLASS_CHAR_SEQUENCE) {
1901             return StringDeserializer.instance;
1902         }
1903         if (rawType == CLASS_ITERABLE) {
1904             // [databind#199]: Can and should 'upgrade' to a Collection type:
1905             TypeFactory tf = ctxt.getTypeFactory();
1906             JavaType[] tps = tf.findTypeParameters(type, CLASS_ITERABLE);
1907             JavaType elemType = (tps == null || tps.length != 1) ? TypeFactory.unknownType() : tps[0];
1908             CollectionType ct = tf.constructCollectionType(Collection.class, elemType);
1909             // Should we re-introspect beanDesc? For now let's not...
1910             return createCollectionDeserializer(ctxt, ct, beanDesc);
1911         }
1912         if (rawType == CLASS_MAP_ENTRY) {
1913             // 28-Apr-2015, tatu: TypeFactory does it all for us already so
1914             JavaType kt = type.containedTypeOrUnknown(0);
1915             JavaType vt = type.containedTypeOrUnknown(1);
1916             TypeDeserializer vts = (TypeDeserializer) vt.getTypeHandler();
1917             if (vts == null) {
1918                 vts = findTypeDeserializer(ctxt.getConfig(), vt);
1919             }
1920             JsonDeserializer<Object> valueDeser = vt.getValueHandler();
1921             KeyDeserializer keyDes = (KeyDeserializer) kt.getValueHandler();
1922             return new MapEntryDeserializer(type, keyDes, valueDeser, vts);
1923         }
1924         String clsName = rawType.getName();
1925         if (rawType.isPrimitive() || clsName.startsWith("java.")) {
1926             // Primitives/wrappers, other Numbers:
1927             JsonDeserializer<?> deser = NumberDeserializers.find(rawType, clsName);
1928             if (deser == null) {
1929                 deser = DateDeserializers.find(rawType, clsName);
1930             }
1931             if (deser != null) {
1932                 return deser;
1933             }
1934         }
1935         // and a few Jackson types as well:
1936         if (rawType == TokenBuffer.class) {
1937             return new TokenBufferDeserializer();
1938         }
1939         JsonDeserializer<?> deser = findOptionalStdDeserializer(ctxt, type, beanDesc);
1940         if (deser != null) {
1941             return deser;
1942         }
1943         return JdkDeserializers.find(rawType, clsName);
1944     }
1945 
_findRemappedType(DeserializationConfig config, Class<?> rawType)1946     protected JavaType _findRemappedType(DeserializationConfig config, Class<?> rawType) throws JsonMappingException {
1947         JavaType type = mapAbstractType(config, config.constructType(rawType));
1948         return (type == null || type.hasRawClass(rawType)) ? null : type;
1949     }
1950 
1951     /*
1952     /**********************************************************
1953     /* Helper methods, finding custom deserializers
1954     /**********************************************************
1955      */
1956 
_findCustomTreeNodeDeserializer(Class<? extends JsonNode> type, DeserializationConfig config, BeanDescription beanDesc)1957     protected JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type,
1958             DeserializationConfig config, BeanDescription beanDesc)
1959         throws JsonMappingException
1960     {
1961         for (Deserializers d  : _factoryConfig.deserializers()) {
1962             JsonDeserializer<?> deser = d.findTreeNodeDeserializer(type, config, beanDesc);
1963             if (deser != null) {
1964                 return deser;
1965             }
1966         }
1967         return null;
1968     }
1969 
_findCustomReferenceDeserializer(ReferenceType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)1970     protected JsonDeserializer<?> _findCustomReferenceDeserializer(ReferenceType type,
1971             DeserializationConfig config, BeanDescription beanDesc,
1972             TypeDeserializer contentTypeDeserializer, JsonDeserializer<?> contentDeserializer)
1973         throws JsonMappingException
1974     {
1975         for (Deserializers d  : _factoryConfig.deserializers()) {
1976             JsonDeserializer<?> deser = d.findReferenceDeserializer(type, config, beanDesc,
1977                     contentTypeDeserializer, contentDeserializer);
1978             if (deser != null) {
1979                 return deser;
1980             }
1981         }
1982         return null;
1983     }
1984 
1985     @SuppressWarnings("unchecked")
_findCustomBeanDeserializer(JavaType type, DeserializationConfig config, BeanDescription beanDesc)1986     protected JsonDeserializer<Object> _findCustomBeanDeserializer(JavaType type,
1987             DeserializationConfig config, BeanDescription beanDesc)
1988         throws JsonMappingException
1989     {
1990         for (Deserializers d  : _factoryConfig.deserializers()) {
1991             JsonDeserializer<?> deser = d.findBeanDeserializer(type, config, beanDesc);
1992             if (deser != null) {
1993                 return (JsonDeserializer<Object>) deser;
1994             }
1995         }
1996         return null;
1997     }
1998 
_findCustomArrayDeserializer(ArrayType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)1999     protected JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type,
2000             DeserializationConfig config, BeanDescription beanDesc,
2001             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
2002         throws JsonMappingException
2003     {
2004         for (Deserializers d  : _factoryConfig.deserializers()) {
2005             JsonDeserializer<?> deser = d.findArrayDeserializer(type, config,
2006                     beanDesc, elementTypeDeserializer, elementDeserializer);
2007             if (deser != null) {
2008                 return deser;
2009             }
2010         }
2011         return null;
2012     }
2013 
_findCustomCollectionDeserializer(CollectionType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)2014     protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type,
2015             DeserializationConfig config, BeanDescription beanDesc,
2016             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
2017         throws JsonMappingException
2018     {
2019         for (Deserializers d  : _factoryConfig.deserializers()) {
2020             JsonDeserializer<?> deser = d.findCollectionDeserializer(type, config, beanDesc,
2021                     elementTypeDeserializer, elementDeserializer);
2022             if (deser != null) {
2023                 return deser;
2024             }
2025         }
2026         return null;
2027     }
2028 
_findCustomCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, BeanDescription beanDesc, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)2029     protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type,
2030             DeserializationConfig config, BeanDescription beanDesc,
2031             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
2032         throws JsonMappingException
2033     {
2034         for (Deserializers d  : _factoryConfig.deserializers()) {
2035             JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(type, config, beanDesc,
2036                     elementTypeDeserializer, elementDeserializer);
2037             if (deser != null) {
2038                 return deser;
2039             }
2040         }
2041         return null;
2042     }
2043 
_findCustomEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc)2044     protected JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type,
2045             DeserializationConfig config, BeanDescription beanDesc)
2046         throws JsonMappingException
2047     {
2048         for (Deserializers d  : _factoryConfig.deserializers()) {
2049             JsonDeserializer<?> deser = d.findEnumDeserializer(type, config, beanDesc);
2050             if (deser != null) {
2051                 return deser;
2052             }
2053         }
2054         return null;
2055     }
2056 
_findCustomMapDeserializer(MapType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)2057     protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type,
2058             DeserializationConfig config, BeanDescription beanDesc,
2059             KeyDeserializer keyDeserializer,
2060             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
2061         throws JsonMappingException
2062     {
2063         for (Deserializers d  : _factoryConfig.deserializers()) {
2064             JsonDeserializer<?> deser = d.findMapDeserializer(type, config, beanDesc,
2065                     keyDeserializer, elementTypeDeserializer, elementDeserializer);
2066             if (deser != null) {
2067                 return deser;
2068             }
2069         }
2070         return null;
2071     }
2072 
_findCustomMapLikeDeserializer(MapLikeType type, DeserializationConfig config, BeanDescription beanDesc, KeyDeserializer keyDeserializer, TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)2073     protected JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type,
2074             DeserializationConfig config, BeanDescription beanDesc,
2075             KeyDeserializer keyDeserializer,
2076             TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer)
2077         throws JsonMappingException
2078     {
2079         for (Deserializers d  : _factoryConfig.deserializers()) {
2080             JsonDeserializer<?> deser = d.findMapLikeDeserializer(type, config, beanDesc,
2081                     keyDeserializer, elementTypeDeserializer, elementDeserializer);
2082             if (deser != null) {
2083                 return deser;
2084             }
2085         }
2086         return null;
2087     }
2088 
2089     /*
2090     /**********************************************************
2091     /* Helper methods, value/content/key type introspection
2092     /**********************************************************
2093      */
2094 
2095     /**
2096      * Helper method called to check if a class or method
2097      * has annotation that tells which class to use for deserialization; and if
2098      * so, to instantiate, that deserializer to use.
2099      * Note that deserializer will NOT yet be contextualized so caller needs to
2100      * take care to call contextualization appropriately.
2101      * Returns null if no such annotation found.
2102      */
findDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann)2103     protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationContext ctxt,
2104             Annotated ann)
2105         throws JsonMappingException
2106     {
2107         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2108         if (intr != null) {
2109             Object deserDef = intr.findDeserializer(ann);
2110             if (deserDef != null) {
2111                 return ctxt.deserializerInstance(ann, deserDef);
2112             }
2113         }
2114         return null;
2115     }
2116 
2117     /**
2118      * Helper method called to check if a class or method
2119      * has annotation that tells which class to use for deserialization of {@link java.util.Map} keys.
2120      * Returns null if no such annotation found.
2121      */
findKeyDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann)2122     protected KeyDeserializer findKeyDeserializerFromAnnotation(DeserializationContext ctxt,
2123             Annotated ann)
2124             throws JsonMappingException
2125     {
2126         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2127         if (intr != null) {
2128             Object deserDef = intr.findKeyDeserializer(ann);
2129             if (deserDef != null) {
2130                 return ctxt.keyDeserializerInstance(ann, deserDef);
2131             }
2132         }
2133         return null;
2134     }
2135 
2136     /**
2137      * @since 2.9
2138      */
findContentDeserializerFromAnnotation(DeserializationContext ctxt, Annotated ann)2139     protected JsonDeserializer<Object> findContentDeserializerFromAnnotation(DeserializationContext ctxt,
2140             Annotated ann)
2141         throws JsonMappingException
2142     {
2143         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2144         if (intr != null) {
2145             Object deserDef = intr.findContentDeserializer(ann);
2146             if (deserDef != null) {
2147                 return ctxt.deserializerInstance(ann, deserDef);
2148             }
2149         }
2150         return null;
2151     }
2152 
2153     /**
2154      * Helper method used to resolve additional type-related annotation information
2155      * like type overrides, or handler (serializer, deserializer) overrides,
2156      * so that from declared field, property or constructor parameter type
2157      * is used as the base and modified based on annotations, if any.
2158      *
2159      * @since 2.8 Combines functionality of <code>modifyTypeByAnnotation</code>
2160      *     and <code>resolveType</code>
2161      */
resolveMemberAndTypeAnnotations(DeserializationContext ctxt, AnnotatedMember member, JavaType type)2162     protected JavaType resolveMemberAndTypeAnnotations(DeserializationContext ctxt,
2163             AnnotatedMember member, JavaType type)
2164         throws JsonMappingException
2165     {
2166         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2167         if (intr == null) {
2168             return type;
2169         }
2170 
2171         // First things first: see if we can find annotations on declared
2172         // type
2173 
2174         if (type.isMapLikeType()) {
2175             JavaType keyType = type.getKeyType();
2176             if (keyType != null) {
2177                 Object kdDef = intr.findKeyDeserializer(member);
2178                 KeyDeserializer kd = ctxt.keyDeserializerInstance(member, kdDef);
2179                 if (kd != null) {
2180                     type = ((MapLikeType) type).withKeyValueHandler(kd);
2181                     keyType = type.getKeyType(); // just in case it's used below
2182                 }
2183             }
2184         }
2185 
2186         if (type.hasContentType()) { // that is, is either container- or reference-type
2187             Object cdDef = intr.findContentDeserializer(member);
2188             JsonDeserializer<?> cd = ctxt.deserializerInstance(member, cdDef);
2189             if (cd != null) {
2190                 type = type.withContentValueHandler(cd);
2191             }
2192             TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(
2193                     ctxt.getConfig(), type, (AnnotatedMember) member);
2194             if (contentTypeDeser != null) {
2195                 type = type.withContentTypeHandler(contentTypeDeser);
2196             }
2197         }
2198         TypeDeserializer valueTypeDeser = findPropertyTypeDeserializer(ctxt.getConfig(),
2199                     type, (AnnotatedMember) member);
2200         if (valueTypeDeser != null) {
2201             type = type.withTypeHandler(valueTypeDeser);
2202         }
2203 
2204         // Second part: find actual type-override annotations on member, if any
2205 
2206         // 18-Jun-2016, tatu: Should we re-do checks for annotations on refined
2207         //   subtypes as well? Code pre-2.8 did not do this, but if we get bug
2208         //   reports may need to consider
2209         type = intr.refineDeserializationType(ctxt.getConfig(), member, type);
2210         return type;
2211     }
2212 
constructEnumResolver(Class<?> enumClass, DeserializationConfig config, AnnotatedMember jsonValueAccessor)2213     protected EnumResolver constructEnumResolver(Class<?> enumClass,
2214             DeserializationConfig config, AnnotatedMember jsonValueAccessor)
2215     {
2216         if (jsonValueAccessor != null) {
2217             if (config.canOverrideAccessModifiers()) {
2218                 ClassUtil.checkAndFixAccess(jsonValueAccessor.getMember(),
2219                         config.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
2220             }
2221             return EnumResolver.constructUnsafeUsingMethod(enumClass,
2222                     jsonValueAccessor, config.getAnnotationIntrospector());
2223         }
2224         // 14-Mar-2016, tatu: We used to check `DeserializationFeature.READ_ENUMS_USING_TO_STRING`
2225         //   here, but that won't do: it must be dynamically changeable...
2226         return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector());
2227     }
2228 
2229     /**
2230      * @since 2.9
2231      */
_hasCreatorAnnotation(DeserializationContext ctxt, Annotated ann)2232     protected boolean _hasCreatorAnnotation(DeserializationContext ctxt,
2233             Annotated ann) {
2234         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2235         if (intr != null) {
2236             JsonCreator.Mode mode = intr.findCreatorAnnotation(ctxt.getConfig(), ann);
2237             return (mode != null) && (mode != JsonCreator.Mode.DISABLED);
2238         }
2239         return false;
2240     }
2241 
2242     /*
2243     /**********************************************************
2244     /* Deprecated helper methods
2245     /**********************************************************
2246      */
2247 
2248     /**
2249      * Method called to see if given method has annotations that indicate
2250      * a more specific type than what the argument specifies.
2251      *
2252      * @deprecated Since 2.8; call {@link #resolveMemberAndTypeAnnotations} instead
2253      */
2254     @Deprecated
modifyTypeByAnnotation(DeserializationContext ctxt, Annotated a, JavaType type)2255     protected JavaType modifyTypeByAnnotation(DeserializationContext ctxt,
2256             Annotated a, JavaType type)
2257         throws JsonMappingException
2258     {
2259         AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
2260         if (intr == null) {
2261             return type;
2262         }
2263         return intr.refineDeserializationType(ctxt.getConfig(), a, type);
2264     }
2265 
2266     /**
2267      * @deprecated since 2.8 call {@link #resolveMemberAndTypeAnnotations} instead.
2268      */
2269     @Deprecated // since 2.8
resolveType(DeserializationContext ctxt, BeanDescription beanDesc, JavaType type, AnnotatedMember member)2270     protected JavaType resolveType(DeserializationContext ctxt,
2271             BeanDescription beanDesc, JavaType type, AnnotatedMember member)
2272         throws JsonMappingException
2273     {
2274         return resolveMemberAndTypeAnnotations(ctxt, member, type);
2275     }
2276 
2277     /**
2278      * @deprecated since 2.8 call <code>findJsonValueMethod</code> on {@link BeanDescription} instead
2279      */
2280     @Deprecated // not used, possibly remove as early as 2.9
_findJsonValueFor(DeserializationConfig config, JavaType enumType)2281     protected AnnotatedMethod _findJsonValueFor(DeserializationConfig config, JavaType enumType)
2282     {
2283         if (enumType == null) {
2284             return null;
2285         }
2286         BeanDescription beanDesc = config.introspect(enumType);
2287         return beanDesc.findJsonValueMethod();
2288     }
2289 
2290     /**
2291      * Helper class to contain default mappings for abstract JDK {@link java.util.Collection}
2292      * and {@link java.util.Map} types. Separated out here to defer cost of creating lookups
2293      * until mappings are actually needed.
2294      *
2295      * @since 2.10
2296      */
2297     @SuppressWarnings("rawtypes")
2298     protected static class ContainerDefaultMappings {
2299         // We do some defaulting for abstract Collection classes and
2300         // interfaces, to avoid having to use exact types or annotations in
2301         // cases where the most common concrete Collection will do.
2302         final static HashMap<String, Class<? extends Collection>> _collectionFallbacks;
2303         static {
2304             HashMap<String, Class<? extends Collection>> fallbacks = new HashMap<>();
2305 
2306             final Class<? extends Collection> DEFAULT_LIST = ArrayList.class;
2307             final Class<? extends Collection> DEFAULT_SET = HashSet.class;
2308 
Collection.class.getName()2309             fallbacks.put(Collection.class.getName(), DEFAULT_LIST);
List.class.getName()2310             fallbacks.put(List.class.getName(), DEFAULT_LIST);
Set.class.getName()2311             fallbacks.put(Set.class.getName(), DEFAULT_SET);
SortedSet.class.getName()2312             fallbacks.put(SortedSet.class.getName(), TreeSet.class);
Queue.class.getName()2313             fallbacks.put(Queue.class.getName(), LinkedList.class);
2314 
2315             // 09-Feb-2019, tatu: How did we miss these? Related in [databind#2251] problem
AbstractList.class.getName()2316             fallbacks.put(AbstractList.class.getName(), DEFAULT_LIST);
AbstractSet.class.getName()2317             fallbacks.put(AbstractSet.class.getName(), DEFAULT_SET);
2318 
2319             // 09-Feb-2019, tatu: And more esoteric types added in JDK6
Deque.class.getName()2320             fallbacks.put(Deque.class.getName(), LinkedList.class);
NavigableSet.class.getName()2321             fallbacks.put(NavigableSet.class.getName(), TreeSet.class);
2322 
2323             _collectionFallbacks = fallbacks;
2324         }
2325 
2326         // We do some defaulting for abstract Map classes and
2327         // interfaces, to avoid having to use exact types or annotations in
2328         // cases where the most common concrete Maps will do.
2329         final static HashMap<String, Class<? extends Map>> _mapFallbacks;
2330         static {
2331             HashMap<String, Class<? extends Map>> fallbacks = new HashMap<>();
2332 
2333             final Class<? extends Map> DEFAULT_MAP = LinkedHashMap.class;
Map.class.getName()2334             fallbacks.put(Map.class.getName(), DEFAULT_MAP);
AbstractMap.class.getName()2335             fallbacks.put(AbstractMap.class.getName(), DEFAULT_MAP);
ConcurrentMap.class.getName()2336             fallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class);
SortedMap.class.getName()2337             fallbacks.put(SortedMap.class.getName(), TreeMap.class);
2338 
java.util.NavigableMap.class.getName()2339             fallbacks.put(java.util.NavigableMap.class.getName(), TreeMap.class);
java.util.concurrent.ConcurrentNavigableMap.class.getName()2340             fallbacks.put(java.util.concurrent.ConcurrentNavigableMap.class.getName(),
2341                     java.util.concurrent.ConcurrentSkipListMap.class);
2342 
2343             _mapFallbacks = fallbacks;
2344         }
2345 
findCollectionFallback(JavaType type)2346         public static Class<?> findCollectionFallback(JavaType type) {
2347             return _collectionFallbacks.get(type.getRawClass().getName());
2348         }
2349 
findMapFallback(JavaType type)2350         public static Class<?> findMapFallback(JavaType type) {
2351             return _mapFallbacks.get(type.getRawClass().getName());
2352         }
2353     }
2354 }
2355