• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.deser;
2 
3 import java.io.IOException;
4 import java.lang.reflect.Constructor;
5 import java.lang.reflect.InvocationTargetException;
6 import java.util.*;
7 
8 import com.fasterxml.jackson.annotation.*;
9 
10 import com.fasterxml.jackson.core.*;
11 import com.fasterxml.jackson.core.JsonParser.NumberType;
12 
13 import com.fasterxml.jackson.databind.*;
14 import com.fasterxml.jackson.databind.deser.impl.*;
15 import com.fasterxml.jackson.databind.deser.std.StdDelegatingDeserializer;
16 import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
17 import com.fasterxml.jackson.databind.exc.IgnoredPropertyException;
18 import com.fasterxml.jackson.databind.introspect.*;
19 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
20 import com.fasterxml.jackson.databind.type.ClassKey;
21 import com.fasterxml.jackson.databind.type.LogicalType;
22 import com.fasterxml.jackson.databind.util.*;
23 
24 /**
25  * Base class for <code>BeanDeserializer</code>.
26  */
27 public abstract class BeanDeserializerBase
28     extends StdDeserializer<Object>
29     implements ContextualDeserializer, ResolvableDeserializer,
30         ValueInstantiator.Gettable, // since 2.9
31         java.io.Serializable // since 2.1
32 {
33     private static final long serialVersionUID = 1;
34 
35     protected final static PropertyName TEMP_PROPERTY_NAME = new PropertyName("#temporary-name");
36 
37     /*
38     /**********************************************************
39     /* Information regarding type being deserialized
40     /**********************************************************
41      */
42 
43     /**
44      * Declared type of the bean this deserializer handles.
45      */
46     final protected JavaType _beanType;
47 
48     /**
49      * Requested shape from bean class annotations.
50      */
51     final protected JsonFormat.Shape _serializationShape;
52 
53     /*
54     /**********************************************************
55     /* Configuration for creating value instance
56     /**********************************************************
57      */
58 
59     /**
60      * Object that handles details of constructing initial
61      * bean value (to which bind data to), unless instance
62      * is passed (via updateValue())
63      */
64     protected final ValueInstantiator _valueInstantiator;
65 
66     /**
67      * Deserializer that is used iff delegate-based creator is
68      * to be used for deserializing from JSON Object.
69      */
70     protected JsonDeserializer<Object> _delegateDeserializer;
71 
72     /**
73      * Deserializer that is used iff array-delegate-based creator
74      * is to be used for deserializing from JSON Object.
75      */
76     protected JsonDeserializer<Object> _arrayDelegateDeserializer;
77 
78     /**
79      * If the bean needs to be instantiated using constructor
80      * or factory method
81      * that takes one or more named properties as argument(s),
82      * this creator is used for instantiation.
83      * This value gets resolved during general resolution.
84      */
85     protected PropertyBasedCreator _propertyBasedCreator;
86 
87     /**
88      * Flag that is set to mark cases where deserialization from Object value
89      * using otherwise "standard" property binding will need to use non-default
90      * creation method: namely, either "full" delegation (array-delegation does
91      * not apply), or properties-based Creator method is used.
92      *<p>
93      * Note that flag is somewhat mis-named as it is not affected by scalar-delegating
94      * creators; it only has effect on Object Value binding.
95      */
96     protected boolean _nonStandardCreation;
97 
98     /**
99      * Flag that indicates that no "special features" whatsoever
100      * are enabled, so the simplest processing is possible.
101      */
102     protected boolean _vanillaProcessing;
103 
104     /*
105     /**********************************************************
106     /* Property information, setters
107     /**********************************************************
108      */
109 
110     /**
111      * Mapping of property names to properties, built when all properties
112      * to use have been successfully resolved.
113      */
114     final protected BeanPropertyMap _beanProperties;
115 
116     /**
117      * List of {@link ValueInjector}s, if any injectable values are
118      * expected by the bean; otherwise null.
119      * This includes injectors used for injecting values via setters
120      * and fields, but not ones passed through constructor parameters.
121      */
122     final protected ValueInjector[] _injectables;
123 
124     /**
125      * Fallback setter used for handling any properties that are not
126      * mapped to regular setters. If setter is not null, it will be
127      * called once for each such property.
128      */
129     protected SettableAnyProperty _anySetter;
130 
131     /**
132      * In addition to properties that are set, we will also keep
133      * track of recognized but ignorable properties: these will
134      * be skipped without errors or warnings.
135      */
136     final protected Set<String> _ignorableProps;
137 
138     /**
139      * Keep track of the the properties that needs to be specifically included.
140      */
141     final protected Set<String> _includableProps;
142 
143     /**
144      * Flag that can be set to ignore and skip unknown properties.
145      * If set, will not throw an exception for unknown properties.
146      */
147     final protected boolean _ignoreAllUnknown;
148 
149     /**
150      * Flag that indicates that some aspect of deserialization depends
151      * on active view used (if any)
152      */
153     final protected boolean _needViewProcesing;
154 
155     /**
156      * We may also have one or more back reference fields (usually
157      * zero or one).
158      */
159     final protected Map<String, SettableBeanProperty> _backRefs;
160 
161     /*
162     /**********************************************************
163     /* Related handlers
164     /**********************************************************
165      */
166 
167     /**
168      * Lazily constructed map used to contain deserializers needed
169      * for polymorphic subtypes.
170      * Note that this is <b>only needed</b> for polymorphic types,
171      * that is, when the actual type is not statically known.
172      * For other types this remains null.
173      */
174     protected transient HashMap<ClassKey, JsonDeserializer<Object>> _subDeserializers;
175 
176     /**
177      * If one of properties has "unwrapped" value, we need separate
178      * helper object
179      */
180     protected UnwrappedPropertyHandler _unwrappedPropertyHandler;
181 
182     /**
183      * Handler that we need iff any of properties uses external
184      * type id.
185      */
186     protected ExternalTypeHandler _externalTypeIdHandler;
187 
188     /**
189      * If an Object Id is to be used for value handled by this
190      * deserializer, this reader is used for handling.
191      */
192     protected final ObjectIdReader _objectIdReader;
193 
194     /*
195     /**********************************************************
196     /* Life-cycle, construction, initialization
197     /**********************************************************
198      */
199 
200     /**
201      * Constructor used when initially building a deserializer
202      * instance, given a {@link BeanDeserializerBuilder} that
203      * contains configuration.
204      */
BeanDeserializerBase(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps, boolean hasViews)205     protected BeanDeserializerBase(BeanDeserializerBuilder builder,
206             BeanDescription beanDesc,
207             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
208             Set<String> ignorableProps, boolean ignoreAllUnknown,
209             Set<String> includableProps,
210             boolean hasViews)
211     {
212         super(beanDesc.getType());
213         _beanType = beanDesc.getType();
214         _valueInstantiator = builder.getValueInstantiator();
215 
216         _beanProperties = properties;
217         _backRefs = backRefs;
218         _ignorableProps = ignorableProps;
219         _ignoreAllUnknown = ignoreAllUnknown;
220         _includableProps = includableProps;
221 
222         _anySetter = builder.getAnySetter();
223         List<ValueInjector> injectables = builder.getInjectables();
224         _injectables = (injectables == null || injectables.isEmpty()) ? null
225                 : injectables.toArray(new ValueInjector[injectables.size()]);
226         _objectIdReader = builder.getObjectIdReader();
227 
228         // 02-May-2020, tatu: This boolean setting is only used when binding from
229         //    Object value, and hence does not consider "array-delegating" or various
230         //    scalar-delegation cases. It is set when default (0-argument) constructor
231         //    is NOT to be used when binding an Object value (or in case of
232         //    POJO-as-array, Array value).
233         _nonStandardCreation = (_unwrappedPropertyHandler != null)
234             || _valueInstantiator.canCreateUsingDelegate()
235         // [databind#2486]: as per above, array-delegating creator should not be considered
236         //   as doing so will prevent use of Array-or-standard-Object deserialization
237         //            || _valueInstantiator.canCreateUsingArrayDelegate()
238             || _valueInstantiator.canCreateFromObjectWith()
239             || !_valueInstantiator.canCreateUsingDefault()
240             ;
241 
242         // Any transformation we may need to apply?
243         final JsonFormat.Value format = beanDesc.findExpectedFormat(null);
244         _serializationShape = format.getShape();
245 
246         _needViewProcesing = hasViews;
247         _vanillaProcessing = !_nonStandardCreation
248                 && (_injectables == null)
249                 && !_needViewProcesing
250                 // also, may need to reorder stuff if we expect Object Id:
251                 && (_objectIdReader == null)
252                 ;
253     }
254 
BeanDeserializerBase(BeanDeserializerBase src)255     protected BeanDeserializerBase(BeanDeserializerBase src) {
256         this(src, src._ignoreAllUnknown);
257     }
258 
BeanDeserializerBase(BeanDeserializerBase src, boolean ignoreAllUnknown)259     protected BeanDeserializerBase(BeanDeserializerBase src, boolean ignoreAllUnknown)
260     {
261         super(src._beanType);
262 
263         _beanType = src._beanType;
264 
265         _valueInstantiator = src._valueInstantiator;
266         _delegateDeserializer = src._delegateDeserializer;
267         _propertyBasedCreator = src._propertyBasedCreator;
268 
269         _beanProperties = src._beanProperties;
270         _backRefs = src._backRefs;
271         _ignorableProps = src._ignorableProps;
272         _ignoreAllUnknown = ignoreAllUnknown;
273         _includableProps = src._includableProps;
274         _anySetter = src._anySetter;
275         _injectables = src._injectables;
276         _objectIdReader = src._objectIdReader;
277 
278         _nonStandardCreation = src._nonStandardCreation;
279         _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
280         _needViewProcesing = src._needViewProcesing;
281         _serializationShape = src._serializationShape;
282 
283         _vanillaProcessing = src._vanillaProcessing;
284     }
285 
BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapper)286     protected BeanDeserializerBase(BeanDeserializerBase src, NameTransformer unwrapper)
287     {
288         super(src._beanType);
289 
290         _beanType = src._beanType;
291 
292         _valueInstantiator = src._valueInstantiator;
293         _delegateDeserializer = src._delegateDeserializer;
294         _propertyBasedCreator = src._propertyBasedCreator;
295 
296         _backRefs = src._backRefs;
297         _ignorableProps = src._ignorableProps;
298         _ignoreAllUnknown = (unwrapper != null) || src._ignoreAllUnknown;
299         _includableProps = src._includableProps;
300         _anySetter = src._anySetter;
301         _injectables = src._injectables;
302         _objectIdReader = src._objectIdReader;
303 
304         _nonStandardCreation = src._nonStandardCreation;
305         UnwrappedPropertyHandler uph = src._unwrappedPropertyHandler;
306 
307         if (unwrapper != null) {
308             // delegate further unwraps, if any
309             if (uph != null) { // got handler, delegate
310                 uph = uph.renameAll(unwrapper);
311             }
312             // and handle direct unwrapping as well:
313             _beanProperties = src._beanProperties.renameAll(unwrapper);
314         } else {
315             _beanProperties = src._beanProperties;
316         }
317         _unwrappedPropertyHandler = uph;
318         _needViewProcesing = src._needViewProcesing;
319         _serializationShape = src._serializationShape;
320 
321         // probably adds a twist, so:
322         _vanillaProcessing = false;
323     }
324 
BeanDeserializerBase(BeanDeserializerBase src, ObjectIdReader oir)325     public BeanDeserializerBase(BeanDeserializerBase src, ObjectIdReader oir)
326     {
327         super(src._beanType);
328         _beanType = src._beanType;
329 
330         _valueInstantiator = src._valueInstantiator;
331         _delegateDeserializer = src._delegateDeserializer;
332         _propertyBasedCreator = src._propertyBasedCreator;
333 
334         _backRefs = src._backRefs;
335         _ignorableProps = src._ignorableProps;
336         _ignoreAllUnknown = src._ignoreAllUnknown;
337         _includableProps = src._includableProps;
338         _anySetter = src._anySetter;
339         _injectables = src._injectables;
340 
341         _nonStandardCreation = src._nonStandardCreation;
342         _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
343         _needViewProcesing = src._needViewProcesing;
344         _serializationShape = src._serializationShape;
345 
346         // then actual changes:
347         _objectIdReader = oir;
348 
349         if (oir == null) {
350             _beanProperties = src._beanProperties;
351             _vanillaProcessing = src._vanillaProcessing;
352         } else {
353             /* 18-Nov-2012, tatu: May or may not have annotations for id property;
354              *   but no easy access. But hard to see id property being optional,
355              *   so let's consider required at this point.
356              */
357             ObjectIdValueProperty idProp = new ObjectIdValueProperty(oir, PropertyMetadata.STD_REQUIRED);
358             _beanProperties = src._beanProperties.withProperty(idProp);
359             _vanillaProcessing = false;
360         }
361     }
362 
363     /**
364      * @since 2.12
365      */
BeanDeserializerBase(BeanDeserializerBase src, Set<String> ignorableProps, Set<String> includableProps)366     public BeanDeserializerBase(BeanDeserializerBase src,
367             Set<String> ignorableProps, Set<String> includableProps)
368     {
369         super(src._beanType);
370         _beanType = src._beanType;
371 
372         _valueInstantiator = src._valueInstantiator;
373         _delegateDeserializer = src._delegateDeserializer;
374         _propertyBasedCreator = src._propertyBasedCreator;
375 
376         _backRefs = src._backRefs;
377         _ignorableProps = ignorableProps;
378         _ignoreAllUnknown = src._ignoreAllUnknown;
379         _includableProps = includableProps;
380         _anySetter = src._anySetter;
381         _injectables = src._injectables;
382 
383         _nonStandardCreation = src._nonStandardCreation;
384         _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
385         _needViewProcesing = src._needViewProcesing;
386         _serializationShape = src._serializationShape;
387 
388         _vanillaProcessing = src._vanillaProcessing;
389         _objectIdReader = src._objectIdReader;
390 
391         // 01-May-2016, tatu: [databind#1217]: Remove properties from mapping,
392         //    to avoid them being deserialized
393         _beanProperties = src._beanProperties.withoutProperties(ignorableProps, includableProps);
394     }
395 
396     /**
397      * @since 2.8
398      */
BeanDeserializerBase(BeanDeserializerBase src, BeanPropertyMap beanProps)399     protected BeanDeserializerBase(BeanDeserializerBase src, BeanPropertyMap beanProps)
400     {
401         super(src._beanType);
402         _beanType = src._beanType;
403 
404         _valueInstantiator = src._valueInstantiator;
405         _delegateDeserializer = src._delegateDeserializer;
406         _propertyBasedCreator = src._propertyBasedCreator;
407 
408         _beanProperties = beanProps;
409         _backRefs = src._backRefs;
410         _ignorableProps = src._ignorableProps;
411         _ignoreAllUnknown = src._ignoreAllUnknown;
412         _includableProps = src._includableProps;
413         _anySetter = src._anySetter;
414         _injectables = src._injectables;
415         _objectIdReader = src._objectIdReader;
416 
417         _nonStandardCreation = src._nonStandardCreation;
418         _unwrappedPropertyHandler = src._unwrappedPropertyHandler;
419         _needViewProcesing = src._needViewProcesing;
420         _serializationShape = src._serializationShape;
421 
422         _vanillaProcessing = src._vanillaProcessing;
423     }
424 
425     @Deprecated // since 2.12
BeanDeserializerBase(BeanDeserializerBase src, Set<String> ignorableProps)426     protected BeanDeserializerBase(BeanDeserializerBase src, Set<String> ignorableProps)
427     {
428         this(src, ignorableProps, src._includableProps);
429     }
430 
431     @Override
unwrappingDeserializer(NameTransformer unwrapper)432     public abstract JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper);
433 
withObjectIdReader(ObjectIdReader oir)434     public abstract BeanDeserializerBase withObjectIdReader(ObjectIdReader oir);
435 
436     /**
437      * @since 2.12
438      */
withByNameInclusion(Set<String> ignorableProps, Set<String> includableProps)439     public abstract BeanDeserializerBase withByNameInclusion(Set<String> ignorableProps, Set<String> includableProps);
440 
441     /**
442      * @since 2.11
443      */
withIgnoreAllUnknown(boolean ignoreUnknown)444     public abstract BeanDeserializerBase withIgnoreAllUnknown(boolean ignoreUnknown);
445 
446     /**
447      * Mutant factory method that custom sub-classes must override; not left as
448      * abstract to prevent more drastic backwards compatibility problems.
449      *
450      * @since 2.8
451      */
withBeanProperties(BeanPropertyMap props)452     public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
453         throw new UnsupportedOperationException("Class "+getClass().getName()
454                 +" does not override `withBeanProperties()`, needs to");
455     }
456 
457     /**
458      * Fluent factory for creating a variant that can handle
459      * POJO output as a JSON Array. Implementations may ignore this request
460      * if no such input is possible.
461      *
462      * @since 2.1
463      */
asArrayDeserializer()464     protected abstract BeanDeserializerBase asArrayDeserializer();
465 
466     /**
467      * @deprecated Since 2.12 use {@link #withByNameInclusion} instead
468      */
469     @Deprecated
withIgnorableProperties(Set<String> ignorableProps)470     public BeanDeserializerBase withIgnorableProperties(Set<String> ignorableProps) {
471         return withByNameInclusion(ignorableProps, _includableProps);
472     }
473 
474     /*
475     /**********************************************************
476     /* Validation, post-processing
477     /**********************************************************
478      */
479 
480     /**
481      * Method called to finalize setup of this deserializer,
482      * after deserializer itself has been registered.
483      * This is needed to handle recursive and transitive dependencies.
484      */
485     @Override
resolve(DeserializationContext ctxt)486     public void resolve(DeserializationContext ctxt) throws JsonMappingException
487     {
488         ExternalTypeHandler.Builder extTypes = null;
489         // if ValueInstantiator can use "creator" approach, need to resolve it here...
490         SettableBeanProperty[] creatorProps;
491 
492         if (_valueInstantiator.canCreateFromObjectWith()) {
493             creatorProps = _valueInstantiator.getFromObjectArguments(ctxt.getConfig());
494 
495             // 22-Jan-2018, tatu: May need to propagate "ignorable" status (from `Access.READ_ONLY`
496             //     or perhaps class-ignorables) into Creator properties too. Can not just delete,
497             //     at this point, but is needed for further processing down the line
498             if (_ignorableProps != null || _includableProps != null) {
499                 for (int i = 0, end = creatorProps.length; i < end; ++i) {
500                     SettableBeanProperty prop  = creatorProps[i];
501                     if (IgnorePropertiesUtil.shouldIgnore(prop.getName(), _ignorableProps, _includableProps)) {
502                         creatorProps[i].markAsIgnorable();
503                     }
504                 }
505             }
506         } else {
507             creatorProps = null;
508         }
509         UnwrappedPropertyHandler unwrapped = null;
510 
511         // 24-Mar-2017, tatu: Looks like we may have to iterate over
512         //   properties twice, to handle potential issues with recursive
513         //   types (see [databind#1575] f.ex).
514         // First loop: find deserializer if not yet known, but do not yet
515         // contextualize (since that can lead to problems with self-references)
516         // 22-Jan-2018, tatu: NOTE! Need not check for `isIgnorable` as that can
517         //   only happen for props in `creatorProps`
518 
519         for (SettableBeanProperty prop : _beanProperties) {
520             if (!prop.hasValueDeserializer()) {
521                 // [databind#125]: allow use of converters
522                 JsonDeserializer<?> deser = findConvertingDeserializer(ctxt, prop);
523                 if (deser == null) {
524                     deser = ctxt.findNonContextualValueDeserializer(prop.getType());
525                 }
526                 SettableBeanProperty newProp = prop.withValueDeserializer(deser);
527                 _replaceProperty(_beanProperties, creatorProps, prop, newProp);
528             }
529         }
530 
531         // Second loop: contextualize, find other pieces
532         for (SettableBeanProperty origProp : _beanProperties) {
533             SettableBeanProperty prop = origProp;
534             JsonDeserializer<?> deser = prop.getValueDeserializer();
535             deser = ctxt.handlePrimaryContextualization(deser, prop, prop.getType());
536             prop = prop.withValueDeserializer(deser);
537             // Need to link managed references with matching back references
538             prop = _resolveManagedReferenceProperty(ctxt, prop);
539 
540             // [databind#351]: need to wrap properties that require object id resolution.
541             if (!(prop instanceof ManagedReferenceProperty)) {
542                 prop = _resolvedObjectIdProperty(ctxt, prop);
543             }
544             // Support unwrapped values (via @JsonUnwrapped)
545             NameTransformer xform = _findPropertyUnwrapper(ctxt, prop);
546             if (xform != null) {
547                 JsonDeserializer<Object> orig = prop.getValueDeserializer();
548                 JsonDeserializer<Object> unwrapping = orig.unwrappingDeserializer(xform);
549                 if (unwrapping != orig && unwrapping != null) {
550                     prop = prop.withValueDeserializer(unwrapping);
551                     if (unwrapped == null) {
552                         unwrapped = new UnwrappedPropertyHandler();
553                     }
554                     unwrapped.addProperty(prop);
555                     // 12-Dec-2014, tatu: As per [databind#647], we will have problems if
556                     //    the original property is left in place. So let's remove it now.
557                     // 25-Mar-2017, tatu: Wonder if this could be problematic wrt creators?
558                     //    (that is, should be remove it from creator too)
559                     _beanProperties.remove(prop);
560                     continue;
561                 }
562             }
563 
564             // 26-Oct-2016, tatu: Need to have access to value deserializer to know if
565             //   merging needed, and now seems to be reasonable time to do that.
566             final PropertyMetadata md = prop.getMetadata();
567             prop = _resolveMergeAndNullSettings(ctxt, prop, md);
568 
569             // non-static inner classes too:
570             prop = _resolveInnerClassValuedProperty(ctxt, prop);
571             if (prop != origProp) {
572                 _replaceProperty(_beanProperties, creatorProps, origProp, prop);
573             }
574 
575             // one more thing: if this property uses "external property" type inclusion,
576             // it needs different handling altogether
577             if (prop.hasValueTypeDeserializer()) {
578                 TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
579                 if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
580                     if (extTypes == null) {
581                         extTypes = ExternalTypeHandler.builder(_beanType);
582                     }
583                     extTypes.addExternal(prop, typeDeser);
584                     // In fact, remove from list of known properties to simplify later handling
585                     _beanProperties.remove(prop);
586                     continue;
587                 }
588             }
589         }
590         // "any setter" may also need to be resolved now
591         if ((_anySetter != null) && !_anySetter.hasValueDeserializer()) {
592             _anySetter = _anySetter.withValueDeserializer(findDeserializer(ctxt,
593                     _anySetter.getType(), _anySetter.getProperty()));
594         }
595         // as well as delegate-based constructor:
596         if (_valueInstantiator.canCreateUsingDelegate()) {
597             JavaType delegateType = _valueInstantiator.getDelegateType(ctxt.getConfig());
598             if (delegateType == null) {
599                 ctxt.reportBadDefinition(_beanType, String.format(
600 "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'",
601                     _beanType, _valueInstantiator.getClass().getName()));
602             }
603             _delegateDeserializer = _findDelegateDeserializer(ctxt, delegateType,
604                     _valueInstantiator.getDelegateCreator());
605         }
606 
607         // and array-delegate-based constructor:
608         if (_valueInstantiator.canCreateUsingArrayDelegate()) {
609             JavaType delegateType = _valueInstantiator.getArrayDelegateType(ctxt.getConfig());
610             if (delegateType == null) {
611                 ctxt.reportBadDefinition(_beanType, String.format(
612 "Invalid delegate-creator definition for %s: value instantiator (%s) returned true for 'canCreateUsingArrayDelegate()', but null for 'getArrayDelegateType()'",
613                         _beanType, _valueInstantiator.getClass().getName()));
614             }
615             _arrayDelegateDeserializer = _findDelegateDeserializer(ctxt, delegateType,
616                     _valueInstantiator.getArrayDelegateCreator());
617         }
618 
619         // And now that we know CreatorProperty instances are also resolved can finally create the creator:
620         if (creatorProps != null) {
621             _propertyBasedCreator = PropertyBasedCreator.construct(ctxt, _valueInstantiator,
622                     creatorProps, _beanProperties);
623         }
624 
625         if (extTypes != null) {
626             // 21-Jun-2016, tatu: related to [databind#999], may need to link type ids too,
627             //    so need to pass collected properties
628             _externalTypeIdHandler = extTypes.build(_beanProperties);
629             // we consider this non-standard, to offline handling
630             _nonStandardCreation = true;
631         }
632 
633         _unwrappedPropertyHandler = unwrapped;
634         if (unwrapped != null) { // we consider this non-standard, to offline handling
635             _nonStandardCreation = true;
636         }
637         // may need to disable vanilla processing, if unwrapped handling was enabled...
638         _vanillaProcessing = _vanillaProcessing && !_nonStandardCreation;
639     }
640 
641     /**
642      * @since 2.8.8
643      */
_replaceProperty(BeanPropertyMap props, SettableBeanProperty[] creatorProps, SettableBeanProperty origProp, SettableBeanProperty newProp)644     protected void _replaceProperty(BeanPropertyMap props, SettableBeanProperty[] creatorProps,
645             SettableBeanProperty origProp, SettableBeanProperty newProp)
646     {
647         props.replace(origProp, newProp);
648         // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
649         if (creatorProps != null) {
650             // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
651             //   fully count on this? May need to revisit in future; seems to hold for now.
652             for (int i = 0, len = creatorProps.length; i < len; ++i) {
653                 if (creatorProps[i] == origProp) {
654                     creatorProps[i] = newProp;
655                     return;
656                 }
657             }
658             /*
659             // ... as per above, it is possible we'd need to add this as fallback
660             // if (but only if) identity check fails?
661             for (int i = 0, len = creatorProps.length; i < len; ++i) {
662                 if (creatorProps[i].getName().equals(origProp.getName())) {
663                     creatorProps[i] = newProp;
664                     return;
665                 }
666             }
667             */
668         }
669     }
670 
671     @SuppressWarnings("unchecked")
_findDelegateDeserializer(DeserializationContext ctxt, JavaType delegateType, AnnotatedWithParams delegateCreator)672     private JsonDeserializer<Object> _findDelegateDeserializer(DeserializationContext ctxt,
673             JavaType delegateType, AnnotatedWithParams delegateCreator) throws JsonMappingException
674     {
675         // Need to create a temporary property to allow contextual deserializers:
676         BeanProperty.Std property = new BeanProperty.Std(TEMP_PROPERTY_NAME,
677                 delegateType, null, delegateCreator,
678                 PropertyMetadata.STD_OPTIONAL);
679         TypeDeserializer td = delegateType.getTypeHandler();
680         if (td == null) {
681             td = ctxt.getConfig().findTypeDeserializer(delegateType);
682         }
683         // 04-May-2018, tatu: [databind#2021] check if there's custom deserializer attached
684         //    to type (resolved from parameter)
685         JsonDeserializer<Object> dd = delegateType.getValueHandler();
686         if (dd == null) {
687             dd = findDeserializer(ctxt, delegateType, property);
688         } else {
689             dd = (JsonDeserializer<Object>) ctxt.handleSecondaryContextualization(dd, property, delegateType);
690         }
691         if (td != null) {
692             td = td.forProperty(property);
693             return new TypeWrappedDeserializer(td, dd);
694         }
695         return dd;
696     }
697 
698     /**
699      * Helper method that can be used to see if specified property is annotated
700      * to indicate use of a converter for property value (in case of container types,
701      * it is container type itself, not key or content type).
702      *<p>
703      * NOTE: returned deserializer is NOT yet contextualized, caller needs to take
704      * care to do that.
705      *
706      * @since 2.2
707      */
findConvertingDeserializer(DeserializationContext ctxt, SettableBeanProperty prop)708     protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationContext ctxt,
709             SettableBeanProperty prop)
710         throws JsonMappingException
711     {
712         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
713         if (intr != null) {
714             Object convDef = intr.findDeserializationConverter(prop.getMember());
715             if (convDef != null) {
716                 Converter<Object,Object> conv = ctxt.converterInstance(prop.getMember(), convDef);
717                 JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
718                 // 25-Mar-2017, tatu: should not yet contextualize
719 //                JsonDeserializer<?> deser = ctxt.findContextualValueDeserializer(delegateType, prop);
720                 JsonDeserializer<?> deser = ctxt.findNonContextualValueDeserializer(delegateType);
721                 return new StdDelegatingDeserializer<Object>(conv, delegateType, deser);
722             }
723         }
724         return null;
725     }
726 
727     /**
728      * Although most of post-processing is done in resolve(), we only get
729      * access to referring property's annotations here; and this is needed
730      * to support per-property ObjectIds.
731      * We will also consider Shape transformations (read from Array) at this
732      * point, since it may come from either Class definition or property.
733      */
734     @Override
createContextual(DeserializationContext ctxt, BeanProperty property)735     public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
736             BeanProperty property) throws JsonMappingException
737     {
738         ObjectIdReader oir = _objectIdReader;
739 
740         // First: may have an override for Object Id:
741         final AnnotationIntrospector intr = ctxt.getAnnotationIntrospector();
742         final AnnotatedMember accessor = _neitherNull(property, intr) ? property.getMember() : null;
743         if (accessor != null) {
744             ObjectIdInfo objectIdInfo = intr.findObjectIdInfo(accessor);
745             if (objectIdInfo != null) { // some code duplication here as well (from BeanDeserializerFactory)
746                 // 2.1: allow modifications by "id ref" annotations as well:
747                 objectIdInfo = intr.findObjectReferenceInfo(accessor, objectIdInfo);
748 
749                 Class<?> implClass = objectIdInfo.getGeneratorType();
750                 // Property-based generator is trickier
751                 JavaType idType;
752                 SettableBeanProperty idProp;
753                 ObjectIdGenerator<?> idGen;
754                 ObjectIdResolver resolver = ctxt.objectIdResolverInstance(accessor, objectIdInfo);
755                 if (implClass == ObjectIdGenerators.PropertyGenerator.class) {
756                     PropertyName propName = objectIdInfo.getPropertyName();
757                     idProp = findProperty(propName);
758                     if (idProp == null) {
759                         ctxt.reportBadDefinition(_beanType, String.format(
760                                 "Invalid Object Id definition for %s: cannot find property with name '%s'",
761                                 handledType().getName(), propName));
762                     }
763                     idType = idProp.getType();
764                     idGen = new PropertyBasedObjectIdGenerator(objectIdInfo.getScope());
765                 } else { // other types are to be simpler
766                     JavaType type = ctxt.constructType(implClass);
767                     idType = ctxt.getTypeFactory().findTypeParameters(type, ObjectIdGenerator.class)[0];
768                     idProp = null;
769                     idGen = ctxt.objectIdGeneratorInstance(accessor, objectIdInfo);
770                 }
771                 JsonDeserializer<?> deser = ctxt.findRootValueDeserializer(idType);
772                 oir = ObjectIdReader.construct(idType, objectIdInfo.getPropertyName(),
773                 		idGen, deser, idProp, resolver);
774             }
775         }
776         // either way, need to resolve serializer:
777         BeanDeserializerBase contextual = this;
778         if (oir != null && oir != _objectIdReader) {
779             contextual = contextual.withObjectIdReader(oir);
780         }
781         // And possibly add more properties to ignore
782         if (accessor != null) {
783             contextual = _handleByNameInclusion(ctxt, intr, contextual, accessor);
784         }
785 
786         // One more thing: are we asked to serialize POJO as array?
787         JsonFormat.Value format = findFormatOverrides(ctxt, property, handledType());
788         JsonFormat.Shape shape = null;
789         if (format != null) {
790             if (format.hasShape()) {
791                 shape = format.getShape();
792             }
793             // 16-May-2016, tatu: How about per-property case-insensitivity?
794             Boolean B = format.getFeature(JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES);
795             if (B != null) {
796                 BeanPropertyMap propsOrig = _beanProperties;
797                 BeanPropertyMap props = propsOrig.withCaseInsensitivity(B.booleanValue());
798                 if (props != propsOrig) {
799                     contextual = contextual.withBeanProperties(props);
800                 }
801             }
802         }
803 
804         if (shape == null) {
805             shape = _serializationShape;
806         }
807         if (shape == JsonFormat.Shape.ARRAY) {
808             contextual = contextual.asArrayDeserializer();
809         }
810         return contextual;
811     }
812 
813     // @since 2.12
_handleByNameInclusion(DeserializationContext ctxt, AnnotationIntrospector intr, BeanDeserializerBase contextual, AnnotatedMember accessor)814     protected BeanDeserializerBase _handleByNameInclusion(DeserializationContext ctxt,
815             AnnotationIntrospector intr,
816             BeanDeserializerBase contextual,
817             AnnotatedMember accessor) throws JsonMappingException
818     {
819         final DeserializationConfig config = ctxt.getConfig();
820         JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnoralByName(config, accessor);
821 
822         // 30-Mar-2020, tatu: As per [databind#2627], need to also allow
823         //    per-property override to "ignore all unknown".
824         //  NOTE: there is no way to override with `false` because annotation
825         //  defaults to `false` (i.e. can not know if `false` is explicit value)
826         if (ignorals.getIgnoreUnknown() && !_ignoreAllUnknown) {
827             contextual = contextual.withIgnoreAllUnknown(true);
828         }
829 
830         final Set<String> namesToIgnore = ignorals.findIgnoredForDeserialization();
831         final Set<String> prevNamesToIgnore = contextual._ignorableProps;
832         final Set<String> newNamesToIgnore;
833 
834         if (namesToIgnore.isEmpty()) {
835             newNamesToIgnore = prevNamesToIgnore;
836         } else if ((prevNamesToIgnore == null) || prevNamesToIgnore.isEmpty()) {
837             newNamesToIgnore = namesToIgnore;
838         } else {
839             newNamesToIgnore = new HashSet<String>(prevNamesToIgnore);
840             newNamesToIgnore.addAll(namesToIgnore);
841         }
842 
843         final Set<String> prevNamesToInclude = contextual._includableProps;
844         final Set<String> newNamesToInclude = IgnorePropertiesUtil.combineNamesToInclude(prevNamesToInclude,
845                 intr.findPropertyInclusionByName(config, accessor).getIncluded());
846 
847         if ((newNamesToIgnore != prevNamesToIgnore)
848                 || (newNamesToInclude != prevNamesToInclude)) {
849             contextual = contextual.withByNameInclusion(newNamesToIgnore, newNamesToInclude);
850         }
851         return contextual;
852     }
853 
854     /**
855      * Helper method called to see if given property is part of 'managed' property
856      * pair (managed + back reference), and if so, handle resolution details.
857      */
_resolveManagedReferenceProperty(DeserializationContext ctxt, SettableBeanProperty prop)858     protected SettableBeanProperty _resolveManagedReferenceProperty(DeserializationContext ctxt,
859             SettableBeanProperty prop)
860         throws JsonMappingException
861     {
862         String refName = prop.getManagedReferenceName();
863         if (refName == null) {
864             return prop;
865         }
866         JsonDeserializer<?> valueDeser = prop.getValueDeserializer();
867         SettableBeanProperty backProp = valueDeser.findBackReference(refName);
868         if (backProp == null) {
869             ctxt.reportBadDefinition(_beanType, String.format(
870 "Cannot handle managed/back reference '%s': no back reference property found from type %s",
871                     refName, prop.getType()));
872         }
873         // also: verify that type is compatible
874         JavaType referredType = _beanType;
875         JavaType backRefType = backProp.getType();
876         boolean isContainer = prop.getType().isContainerType();
877         if (!backRefType.getRawClass().isAssignableFrom(referredType.getRawClass())) {
878             ctxt.reportBadDefinition(_beanType, String.format(
879 "Cannot handle managed/back reference '%s': back reference type (%s) not compatible with managed type (%s)",
880                     refName, backRefType.getRawClass().getName(),
881                     referredType.getRawClass().getName()));
882         }
883         return new ManagedReferenceProperty(prop, refName, backProp, isContainer);
884     }
885 
886     /**
887      * Method that wraps given property with {@link ObjectIdReferenceProperty}
888      * in case where object id resolution is required.
889      */
_resolvedObjectIdProperty(DeserializationContext ctxt, SettableBeanProperty prop)890     protected SettableBeanProperty _resolvedObjectIdProperty(DeserializationContext ctxt,
891             SettableBeanProperty prop) throws JsonMappingException
892     {
893         ObjectIdInfo objectIdInfo = prop.getObjectIdInfo();
894         JsonDeserializer<Object> valueDeser = prop.getValueDeserializer();
895         ObjectIdReader objectIdReader = (valueDeser == null) ? null : valueDeser.getObjectIdReader();
896         if (objectIdInfo == null && objectIdReader == null) {
897             return prop;
898         }
899         return new ObjectIdReferenceProperty(prop, objectIdInfo);
900     }
901 
902     /**
903      * Helper method called to see if given property might be so-called unwrapped
904      * property: these require special handling.
905      */
_findPropertyUnwrapper(DeserializationContext ctxt, SettableBeanProperty prop)906     protected NameTransformer _findPropertyUnwrapper(DeserializationContext ctxt,
907             SettableBeanProperty prop)
908         throws JsonMappingException
909     {
910         AnnotatedMember am = prop.getMember();
911         if (am != null) {
912             NameTransformer unwrapper = ctxt.getAnnotationIntrospector().findUnwrappingNameTransformer(am);
913             if (unwrapper != null) {
914                 // 01-Dec-2016, tatu: As per [databind#265] we cannot yet support passing
915                 //   of unwrapped values through creator properties, so fail fast
916                 if (prop instanceof CreatorProperty) {
917                     ctxt.reportBadDefinition(getValueType(), String.format(
918                             "Cannot define Creator property \"%s\" as `@JsonUnwrapped`: combination not yet supported",
919                             prop.getName()));
920                 }
921                 return unwrapper;
922             }
923         }
924         return null;
925     }
926 
927     /**
928      * Helper method that will handle gruesome details of dealing with properties
929      * that have non-static inner class as value...
930      */
_resolveInnerClassValuedProperty(DeserializationContext ctxt, SettableBeanProperty prop)931     protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationContext ctxt,
932             SettableBeanProperty prop)
933     {
934         /* Should we encounter a property that has non-static inner-class
935          * as value, we need to add some more magic to find the "hidden" constructor...
936          */
937         JsonDeserializer<Object> deser = prop.getValueDeserializer();
938         // ideally wouldn't rely on it being BeanDeserializerBase; but for now it'll have to do
939         if (deser instanceof BeanDeserializerBase) {
940             BeanDeserializerBase bd = (BeanDeserializerBase) deser;
941             ValueInstantiator vi = bd.getValueInstantiator();
942             if (!vi.canCreateUsingDefault()) { // no default constructor
943                 Class<?> valueClass = prop.getType().getRawClass();
944                 // NOTE: almost same as `isNonStaticInnerClass()` but need to know enclosing...
945                 Class<?> enclosing = ClassUtil.getOuterClass(valueClass);
946                 // and is inner class of the bean class...
947                 if ((enclosing != null) && (enclosing == _beanType.getRawClass())) {
948                     for (Constructor<?> ctor : valueClass.getConstructors()) {
949                         Class<?>[] paramTypes = ctor.getParameterTypes();
950                         if (paramTypes.length == 1) {
951                             if (enclosing.equals(paramTypes[0])) {
952                                 if (ctxt.canOverrideAccessModifiers()) {
953                                     ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
954                                 }
955                                 return new InnerClassProperty(prop, ctor);
956                             }
957                         }
958                     }
959                 }
960             }
961         }
962         return prop;
963     }
964 
965     // @since 2.9
_resolveMergeAndNullSettings(DeserializationContext ctxt, SettableBeanProperty prop, PropertyMetadata propMetadata)966     protected SettableBeanProperty _resolveMergeAndNullSettings(DeserializationContext ctxt,
967             SettableBeanProperty prop, PropertyMetadata propMetadata)
968         throws JsonMappingException
969     {
970         PropertyMetadata.MergeInfo merge = propMetadata.getMergeInfo();
971         // First mergeability
972         if (merge != null) {
973             JsonDeserializer<?> valueDeser = prop.getValueDeserializer();
974             Boolean mayMerge = valueDeser.supportsUpdate(ctxt.getConfig());
975 
976             if (mayMerge == null) {
977                 // we don't really know if it's ok; so only use if explicitly specified
978                 if (merge.fromDefaults) {
979                     return prop;
980                 }
981             } else if (!mayMerge.booleanValue()) { // prevented
982                 if (!merge.fromDefaults) {
983                     // If attempt was made via explicit annotation/per-type config override,
984                     // should be reported; may or may not result in exception
985                     ctxt.handleBadMerge(valueDeser);
986                 }
987                 return prop;
988             }
989             // Anyway; if we get this far, do enable merging
990             AnnotatedMember accessor = merge.getter;
991             accessor.fixAccess(ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
992             if (!(prop instanceof SetterlessProperty)) {
993                 prop = MergingSettableBeanProperty.construct(prop, accessor);
994             }
995         }
996 
997         // And after this, see if we require non-standard null handling
998         NullValueProvider nuller = findValueNullProvider(ctxt, prop, propMetadata);
999         if (nuller != null) {
1000             prop = prop.withNullProvider(nuller);
1001         }
1002         return prop;
1003     }
1004 
1005     /*
1006     /**********************************************************
1007     /* Public accessors; null/empty value providers
1008     /**********************************************************
1009      */
1010 
1011     @Override
getNullAccessPattern()1012     public AccessPattern getNullAccessPattern() {
1013         // POJO types do not have custom `null` values
1014         return AccessPattern.ALWAYS_NULL;
1015     }
1016 
1017     @Override
getEmptyAccessPattern()1018     public AccessPattern getEmptyAccessPattern() {
1019         // Empty values cannot be shared
1020         return AccessPattern.DYNAMIC;
1021     }
1022 
1023     @Override // since 2.9
getEmptyValue(DeserializationContext ctxt)1024     public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingException {
1025         // alas, need to promote exception, if any:
1026         try {
1027             return _valueInstantiator.createUsingDefault(ctxt);
1028         } catch (IOException e) {
1029             return ClassUtil.throwAsMappingException(ctxt, e);
1030         }
1031     }
1032 
1033     /*
1034     /**********************************************************
1035     /* Public accessors; other
1036     /**********************************************************
1037      */
1038 
1039     @Override
isCachable()1040     public boolean isCachable() { return true; }
1041 
1042     /**
1043      * Accessor for checking whether this deserializer is operating
1044      * in case-insensitive manner.
1045      *
1046      * @return True if this deserializer should match property names without
1047      *    considering casing; false if case has to match exactly.
1048      *
1049      * @since 2.12
1050      */
isCaseInsensitive()1051     public boolean isCaseInsensitive() {
1052         return _beanProperties.isCaseInsensitive();
1053     }
1054 
1055     @Override // since 2.9
supportsUpdate(DeserializationConfig config)1056     public Boolean supportsUpdate(DeserializationConfig config) {
1057         // although with possible caveats, yes, values can be updated
1058         // 23-Oct-2016, tatu: Perhaps in future could and should verify from
1059         //   bean settings...
1060         return Boolean.TRUE;
1061     }
1062 
1063     @Override
handledType()1064     public Class<?> handledType() {
1065         return _beanType.getRawClass();
1066     }
1067 
1068     /**
1069      * Overridden to return true for those instances that are
1070      * handling value for which Object Identity handling is enabled
1071      * (either via value type or referring property).
1072      */
1073     @Override
getObjectIdReader()1074     public ObjectIdReader getObjectIdReader() {
1075         return _objectIdReader;
1076     }
1077 
hasProperty(String propertyName)1078     public boolean hasProperty(String propertyName) {
1079         return _beanProperties.find(propertyName) != null;
1080     }
1081 
hasViews()1082     public boolean hasViews() {
1083         return _needViewProcesing;
1084     }
1085 
1086     /**
1087      * Accessor for checking number of deserialized properties.
1088      */
getPropertyCount()1089     public int getPropertyCount() {
1090         return _beanProperties.size();
1091     }
1092 
1093     @Override
getKnownPropertyNames()1094     public Collection<Object> getKnownPropertyNames() {
1095         ArrayList<Object> names = new ArrayList<Object>();
1096         for (SettableBeanProperty prop : _beanProperties) {
1097             names.add(prop.getName());
1098         }
1099         return names;
1100     }
1101 
1102     /**
1103      * @deprecated Since 2.3, use {@link #handledType()} instead
1104      */
1105     @Deprecated
getBeanClass()1106     public final Class<?> getBeanClass() { return _beanType.getRawClass(); }
1107 
1108     @Override
getValueType()1109     public JavaType getValueType() { return _beanType; }
1110 
1111     @Override // since 2.12
logicalType()1112     public LogicalType logicalType() {
1113         return LogicalType.POJO;
1114     }
1115 
1116     /**
1117      * Accessor for iterating over properties this deserializer uses; with
1118      * the exception that properties passed via Creator methods
1119      * (specifically, "property-based constructor") are not included,
1120      * but can be accessed separate by calling
1121      * {@link #creatorProperties}
1122      */
properties()1123     public Iterator<SettableBeanProperty> properties()
1124     {
1125         if (_beanProperties == null) {
1126             throw new IllegalStateException("Can only call after BeanDeserializer has been resolved");
1127         }
1128         return _beanProperties.iterator();
1129     }
1130 
1131     /**
1132      * Accessor for finding properties that represents values to pass
1133      * through property-based creator method (constructor or
1134      * factory method)
1135      *
1136      * @since 2.0
1137      */
creatorProperties()1138     public Iterator<SettableBeanProperty> creatorProperties()
1139     {
1140         if (_propertyBasedCreator == null) {
1141             return Collections.<SettableBeanProperty>emptyList().iterator();
1142         }
1143         return _propertyBasedCreator.properties().iterator();
1144     }
1145 
findProperty(PropertyName propertyName)1146     public SettableBeanProperty findProperty(PropertyName propertyName)
1147     {
1148         // TODO: start matching full name?
1149         return findProperty(propertyName.getSimpleName());
1150     }
1151 
1152     /**
1153      * Accessor for finding the property with given name, if POJO
1154      * has one. Name used is the external name, i.e. name used
1155      * in external data representation (JSON).
1156      *
1157      * @since 2.0
1158      */
findProperty(String propertyName)1159     public SettableBeanProperty findProperty(String propertyName)
1160     {
1161         SettableBeanProperty prop = (_beanProperties == null) ?
1162                 null : _beanProperties.find(propertyName);
1163         if (prop == null && _propertyBasedCreator != null) {
1164             prop = _propertyBasedCreator.findCreatorProperty(propertyName);
1165         }
1166         return prop;
1167     }
1168 
1169     /**
1170      * Alternate find method that tries to locate a property with given
1171      * <code>property index</code>.
1172      * Note that access by index is not necessarily faster than by name,
1173      * since properties are not directly indexable; however, for most
1174      * instances difference is not significant as number of properties
1175      * is low.
1176      *
1177      * @since 2.3
1178      */
findProperty(int propertyIndex)1179     public SettableBeanProperty findProperty(int propertyIndex)
1180     {
1181         SettableBeanProperty prop = (_beanProperties == null) ?
1182                 null : _beanProperties.find(propertyIndex);
1183         if (prop == null && _propertyBasedCreator != null) {
1184             prop = _propertyBasedCreator.findCreatorProperty(propertyIndex);
1185         }
1186         return prop;
1187     }
1188 
1189     /**
1190      * Method needed by {@link BeanDeserializerFactory} to properly link
1191      * managed- and back-reference pairs.
1192      */
1193     @Override
findBackReference(String logicalName)1194     public SettableBeanProperty findBackReference(String logicalName)
1195     {
1196         if (_backRefs == null) {
1197             return null;
1198         }
1199         return _backRefs.get(logicalName);
1200     }
1201 
1202     @Override // ValueInstantiator.Gettable
getValueInstantiator()1203     public ValueInstantiator getValueInstantiator() {
1204         return _valueInstantiator;
1205     }
1206 
1207     /*
1208     /**********************************************************
1209     /* Mutators
1210     /**********************************************************
1211      */
1212 
1213     /**
1214      * Method that can be used to replace an existing property with
1215      * a modified one.
1216      *<p>
1217      * NOTE: only ever use this method if you know what you are doing;
1218      * incorrect usage can break deserializer.
1219      *
1220      * @param original Property to replace
1221      * @param replacement Property to replace it with
1222      *
1223      * @since 2.1
1224      */
replaceProperty(SettableBeanProperty original, SettableBeanProperty replacement)1225     public void replaceProperty(SettableBeanProperty original,
1226             SettableBeanProperty replacement)
1227     {
1228         _beanProperties.replace(original, replacement);
1229     }
1230 
1231     /*
1232     /**********************************************************
1233     /* Partial deserializer implementation
1234     /**********************************************************
1235      */
1236 
1237     /**
1238      * General version used when handling needs more advanced
1239      * features.
1240      */
deserializeFromObject(JsonParser p, DeserializationContext ctxt)1241     public abstract Object deserializeFromObject(JsonParser p, DeserializationContext ctxt)
1242         throws IOException;
1243 
1244     @Override
deserializeWithType(JsonParser p, DeserializationContext ctxt, TypeDeserializer typeDeserializer)1245     public Object deserializeWithType(JsonParser p, DeserializationContext ctxt,
1246             TypeDeserializer typeDeserializer)
1247         throws IOException
1248     {
1249         // 16-Feb-2012, tatu: ObjectId may be used as well... need to check that first
1250         if (_objectIdReader != null) {
1251             // 05-Aug-2013, tatu: May use native Object Id
1252             if (p.canReadObjectId()) {
1253                 Object id = p.getObjectId();
1254                 if (id != null) {
1255                     Object ob = typeDeserializer.deserializeTypedFromObject(p, ctxt);
1256                     return _handleTypedObjectId(p, ctxt, ob, id);
1257                 }
1258             }
1259             // or, Object Ids Jackson explicitly sets
1260             JsonToken t = p.currentToken();
1261             if (t != null) {
1262                 // Most commonly, a scalar (int id, uuid String, ...)
1263                 if (t.isScalarValue()) {
1264                     return deserializeFromObjectId(p, ctxt);
1265                 }
1266                 // but, with 2.5+, a simple Object-wrapped value also legal:
1267                 if (t == JsonToken.START_OBJECT) {
1268                     t = p.nextToken();
1269                 }
1270                 if ((t == JsonToken.FIELD_NAME) && _objectIdReader.maySerializeAsObject()
1271                         && _objectIdReader.isValidReferencePropertyName(p.currentName(), p)) {
1272                     return deserializeFromObjectId(p, ctxt);
1273                 }
1274             }
1275         }
1276         // In future could check current token... for now this should be enough:
1277         return typeDeserializer.deserializeTypedFromObject(p, ctxt);
1278     }
1279 
1280     /**
1281      * Offlined method called to handle "native" Object Id that has been read
1282      * and known to be associated with given deserialized POJO.
1283      *
1284      * @since 2.3
1285      */
_handleTypedObjectId(JsonParser p, DeserializationContext ctxt, Object pojo, Object rawId)1286     protected Object _handleTypedObjectId(JsonParser p, DeserializationContext ctxt,
1287             Object pojo, Object rawId)
1288         throws IOException
1289     {
1290         // One more challenge: type of id may not be type of property we are expecting
1291         // later on; specifically, numeric ids vs Strings.
1292         JsonDeserializer<Object> idDeser = _objectIdReader.getDeserializer();
1293         final Object id;
1294 
1295         // Ok, this is bit ridiculous; let's see if conversion is needed:
1296         if (idDeser.handledType() == rawId.getClass()) {
1297             // nope: already same type
1298             id = rawId;
1299         } else {
1300             id = _convertObjectId(p, ctxt, rawId, idDeser);
1301         }
1302 
1303         ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver);
1304         roid.bindItem(pojo);
1305         // also: may need to set a property value as well
1306         SettableBeanProperty idProp = _objectIdReader.idProperty;
1307         if (idProp != null) {
1308             return idProp.setAndReturn(pojo, id);
1309         }
1310         return pojo;
1311     }
1312 
1313     /**
1314      * Helper method we need to do necessary conversion from whatever native object id
1315      * type is, into declared type that Jackson internals expect. This may be
1316      * simple cast (for String ids), or something more complicated; in latter
1317      * case we may need to create bogus content buffer to allow use of
1318      * id deserializer.
1319      *
1320      * @since 2.3
1321      */
1322     @SuppressWarnings("resource") // TokenBuffers don't need close, nor parser thereof
_convertObjectId(JsonParser p, DeserializationContext ctxt, Object rawId, JsonDeserializer<Object> idDeser)1323     protected Object _convertObjectId(JsonParser p, DeserializationContext ctxt,
1324             Object rawId, JsonDeserializer<Object> idDeser) throws IOException
1325     {
1326         TokenBuffer buf = new TokenBuffer(p, ctxt);
1327         if (rawId instanceof String) {
1328             buf.writeString((String) rawId);
1329         } else if (rawId instanceof Long) {
1330             buf.writeNumber(((Long) rawId).longValue());
1331         } else if (rawId instanceof Integer) {
1332             buf.writeNumber(((Integer) rawId).intValue());
1333         } else {
1334             // should we worry about UUIDs? They should be fine, right?
1335             // 07-Aug-2014, tatu: Maybe, but not necessarily; had issues with
1336             //   Smile format; [dataformat-smile#19], possibly related.
1337             // 01-Sep-2016, tatu: For non-JSON, might want to consider `writeEmbeddedObject`
1338             //   but that won't work for default impl (JSON and most dataformats)
1339             buf.writeObject(rawId);
1340         }
1341         JsonParser bufParser = buf.asParser();
1342         bufParser.nextToken();
1343         return idDeser.deserialize(bufParser, ctxt);
1344     }
1345 
1346     // NOTE: currently only used by standard BeanDeserializer (not Builder-based)
1347     /**
1348      * Alternative deserialization method used when we expect to see Object Id;
1349      * if so, we will need to ensure that the Id is seen before anything
1350      * else, to ensure that it is available for solving references,
1351      * even if JSON itself is not ordered that way. This may require
1352      * buffering in some cases, but usually just a simple lookup to ensure
1353      * that ordering is correct.
1354      */
deserializeWithObjectId(JsonParser p, DeserializationContext ctxt)1355     protected Object deserializeWithObjectId(JsonParser p, DeserializationContext ctxt) throws IOException {
1356         return deserializeFromObject(p, ctxt);
1357     }
1358 
1359     /**
1360      * Method called in cases where it looks like we got an Object Id
1361      * to parse and use as a reference.
1362      */
deserializeFromObjectId(JsonParser p, DeserializationContext ctxt)1363     protected Object deserializeFromObjectId(JsonParser p, DeserializationContext ctxt) throws IOException
1364     {
1365         Object id = _objectIdReader.readObjectReference(p, ctxt);
1366         ReadableObjectId roid = ctxt.findObjectId(id, _objectIdReader.generator, _objectIdReader.resolver);
1367         // do we have it resolved?
1368         Object pojo = roid.resolve();
1369         if (pojo == null) { // not yet; should wait...
1370             throw new UnresolvedForwardReference(p,
1371                     "Could not resolve Object Id ["+id+"] (for "+_beanType+").",
1372                     p.getCurrentLocation(), roid);
1373         }
1374         return pojo;
1375     }
1376 
deserializeFromObjectUsingNonDefault(JsonParser p, DeserializationContext ctxt)1377     protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
1378             DeserializationContext ctxt) throws IOException
1379     {
1380         final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1381         if (delegateDeser != null) {
1382             final Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1383                     delegateDeser.deserialize(p, ctxt));
1384             if (_injectables != null) {
1385                 injectValues(ctxt, bean);
1386             }
1387             return bean;
1388         }
1389         if (_propertyBasedCreator != null) {
1390             return _deserializeUsingPropertyBased(p, ctxt);
1391         }
1392         // 25-Jan-2017, tatu: We do not actually support use of Creators for non-static
1393         //   inner classes -- with one and only one exception; that of default constructor!
1394         //   -- so let's indicate it
1395         Class<?> raw = _beanType.getRawClass();
1396         if (ClassUtil.isNonStaticInnerClass(raw)) {
1397             return ctxt.handleMissingInstantiator(raw, null, p,
1398 "non-static inner classes like this can only by instantiated using default, no-argument constructor");
1399         }
1400         return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
1401                 "cannot deserialize from Object value (no delegate- or property-based Creator)");
1402     }
1403 
_deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt)1404     protected abstract Object _deserializeUsingPropertyBased(final JsonParser p,
1405             final DeserializationContext ctxt) throws IOException;
1406 
deserializeFromNumber(JsonParser p, DeserializationContext ctxt)1407     public Object deserializeFromNumber(JsonParser p, DeserializationContext ctxt)
1408         throws IOException
1409     {
1410         // First things first: id Object Id is used, most likely that's it
1411         if (_objectIdReader != null) {
1412             return deserializeFromObjectId(p, ctxt);
1413         }
1414         final JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1415         NumberType nt = p.getNumberType();
1416         if (nt == NumberType.INT) {
1417             if (delegateDeser != null) {
1418                 if (!_valueInstantiator.canCreateFromInt()) {
1419                     Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1420                             delegateDeser.deserialize(p, ctxt));
1421                     if (_injectables != null) {
1422                         injectValues(ctxt, bean);
1423                     }
1424                     return bean;
1425                 }
1426             }
1427             return _valueInstantiator.createFromInt(ctxt, p.getIntValue());
1428         }
1429         if (nt == NumberType.LONG) {
1430             if (delegateDeser != null) {
1431                 if (!_valueInstantiator.canCreateFromInt()) {
1432                     Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1433                             delegateDeser.deserialize(p, ctxt));
1434                     if (_injectables != null) {
1435                         injectValues(ctxt, bean);
1436                     }
1437                     return bean;
1438                 }
1439             }
1440             return _valueInstantiator.createFromLong(ctxt, p.getLongValue());
1441         }
1442         if (nt == NumberType.BIG_INTEGER) {
1443             if (delegateDeser != null) {
1444                 if (!_valueInstantiator.canCreateFromBigInteger()) {
1445                     Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt));
1446                     if (_injectables != null) {
1447                         injectValues(ctxt, bean);
1448                     }
1449                     return bean;
1450                 }
1451             }
1452             return _valueInstantiator.createFromBigInteger(ctxt, p.getBigIntegerValue());
1453         }
1454 
1455         return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p,
1456                 "no suitable creator method found to deserialize from Number value (%s)",
1457                 p.getNumberValue());
1458     }
1459 
deserializeFromString(JsonParser p, DeserializationContext ctxt)1460     public Object deserializeFromString(JsonParser p, DeserializationContext ctxt)
1461         throws IOException
1462     {
1463         // First things first: id Object Id is used, most likely that's it
1464         if (_objectIdReader != null) {
1465             return deserializeFromObjectId(p, ctxt);
1466         }
1467         // Bit complicated if we have delegating creator; may need to use it,
1468         // or might not...
1469         JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1470         if (delegateDeser != null) {
1471             if (!_valueInstantiator.canCreateFromString()) {
1472                 Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1473                         delegateDeser.deserialize(p, ctxt));
1474                 if (_injectables != null) {
1475                     injectValues(ctxt, bean);
1476                 }
1477                 return bean;
1478             }
1479         }
1480         return _deserializeFromString(p, ctxt);
1481     }
1482 
1483     /**
1484      * Method called to deserialize POJO value from a JSON floating-point
1485      * number.
1486      */
deserializeFromDouble(JsonParser p, DeserializationContext ctxt)1487     public Object deserializeFromDouble(JsonParser p, DeserializationContext ctxt) throws IOException
1488     {
1489         NumberType t = p.getNumberType();
1490         // no separate methods for taking float...
1491         if ((t == NumberType.DOUBLE) || (t == NumberType.FLOAT)) {
1492             JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1493             if (delegateDeser != null) {
1494                 if (!_valueInstantiator.canCreateFromDouble()) {
1495                     Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1496                             delegateDeser.deserialize(p, ctxt));
1497                     if (_injectables != null) {
1498                         injectValues(ctxt, bean);
1499                     }
1500                     return bean;
1501                 }
1502             }
1503             return _valueInstantiator.createFromDouble(ctxt, p.getDoubleValue());
1504         }
1505 
1506         if (t == NumberType.BIG_DECIMAL) {
1507             JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1508             if (delegateDeser != null) {
1509                 if (!_valueInstantiator.canCreateFromBigDecimal()) {
1510                     Object bean = _valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt));
1511                     if (_injectables != null) {
1512                         injectValues(ctxt, bean);
1513                     }
1514                     return bean;
1515                 }
1516             }
1517 
1518             return _valueInstantiator.createFromBigDecimal(ctxt, p.getDecimalValue());
1519         }
1520 
1521         return ctxt.handleMissingInstantiator(handledType(), getValueInstantiator(), p,
1522                 "no suitable creator method found to deserialize from Number value (%s)",
1523                 p.getNumberValue());
1524     }
1525 
1526     /**
1527      * Method called to deserialize POJO value from a JSON boolean value (true, false)
1528      */
deserializeFromBoolean(JsonParser p, DeserializationContext ctxt)1529     public Object deserializeFromBoolean(JsonParser p, DeserializationContext ctxt) throws IOException
1530     {
1531         JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1532         if (delegateDeser != null) {
1533             if (!_valueInstantiator.canCreateFromBoolean()) {
1534                 Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1535                         delegateDeser.deserialize(p, ctxt));
1536                 if (_injectables != null) {
1537                     injectValues(ctxt, bean);
1538                 }
1539                 return bean;
1540             }
1541         }
1542         boolean value = (p.currentToken() == JsonToken.VALUE_TRUE);
1543         return _valueInstantiator.createFromBoolean(ctxt, value);
1544     }
1545 
1546     /**
1547      * @deprecated Since 2.11 Should not be used: was never meant to be called by
1548      *    code other than sub-classes (implementations), and implementations details
1549      *    differ
1550      */
1551     @Deprecated
deserializeFromArray(JsonParser p, DeserializationContext ctxt)1552     public Object deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException {
1553         // should work as subtypes ought to override this method:
1554         return _deserializeFromArray(p, ctxt);
1555     }
1556 
deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt)1557     public Object deserializeFromEmbedded(JsonParser p, DeserializationContext ctxt)
1558         throws IOException
1559     {
1560         // First things first: id Object Id is used, most likely that's it; specifically,
1561         // true for UUIDs when written as binary (with Smile, other binary formats)
1562         if (_objectIdReader != null) {
1563             return deserializeFromObjectId(p, ctxt);
1564         }
1565         // 26-Jul-2017, tatu: as per [databind#1711] need to support delegating case too
1566         JsonDeserializer<Object> delegateDeser = _delegateDeserializer();
1567         if (delegateDeser != null) {
1568             if (!_valueInstantiator.canCreateFromString()) {
1569                 Object bean = _valueInstantiator.createUsingDelegate(ctxt,
1570                         delegateDeser.deserialize(p, ctxt));
1571                 if (_injectables != null) {
1572                     injectValues(ctxt, bean);
1573                 }
1574                 return bean;
1575             }
1576         }
1577         // TODO: maybe add support for ValueInstantiator, embedded?
1578 
1579         // 26-Jul-2017, tatu: related to [databind#1711], let's actually verify assignment
1580         //    compatibility before returning. Bound to catch misconfigured cases and produce
1581         //    more meaningful exceptions.
1582         Object value = p.getEmbeddedObject();
1583         if (value != null) {
1584             if (!_beanType.isTypeOrSuperTypeOf(value.getClass())) {
1585                 // allow this to be handled...
1586                 value = ctxt.handleWeirdNativeValue(_beanType, value, p);
1587             }
1588         }
1589         return value;
1590     }
1591 
1592     /**
1593      * @since 2.9
1594      */
_delegateDeserializer()1595     protected final JsonDeserializer<Object> _delegateDeserializer() {
1596         JsonDeserializer<Object> deser = _delegateDeserializer;
1597         if (deser == null) {
1598             deser = _arrayDelegateDeserializer;
1599         }
1600         return deser;
1601     }
1602 
1603     /*
1604     /**********************************************************
1605     /* Overridable helper methods
1606     /**********************************************************
1607      */
1608 
injectValues(DeserializationContext ctxt, Object bean)1609     protected void injectValues(DeserializationContext ctxt, Object bean)
1610         throws IOException
1611     {
1612         for (ValueInjector injector : _injectables) {
1613             injector.inject(ctxt, bean);
1614         }
1615     }
1616 
1617     /**
1618      * Method called to handle set of one or more unknown properties,
1619      * stored in their entirety in given {@link TokenBuffer}
1620      * (as field entries, name and value).
1621      */
1622     @SuppressWarnings("resource")
handleUnknownProperties(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens)1623     protected Object handleUnknownProperties(DeserializationContext ctxt,
1624             Object bean, TokenBuffer unknownTokens)
1625         throws IOException
1626     {
1627         // First: add closing END_OBJECT as marker
1628         unknownTokens.writeEndObject();
1629 
1630         // note: buffer does NOT have starting START_OBJECT
1631         JsonParser bufferParser = unknownTokens.asParser();
1632         while (bufferParser.nextToken() != JsonToken.END_OBJECT) {
1633             String propName = bufferParser.currentName();
1634             // Unknown: let's call handler method
1635             bufferParser.nextToken();
1636             handleUnknownProperty(bufferParser, ctxt, bean, propName);
1637         }
1638         return bean;
1639     }
1640 
1641     /**
1642      * Helper method called for an unknown property, when using "vanilla"
1643      * processing.
1644      *
1645      * @param beanOrBuilder Either POJO instance (if constructed), or builder
1646      *   (in case of builder-based approach), that has property we haven't been
1647      *   able to handle yet.
1648      */
handleUnknownVanilla(JsonParser p, DeserializationContext ctxt, Object beanOrBuilder, String propName)1649     protected void handleUnknownVanilla(JsonParser p, DeserializationContext ctxt,
1650             Object beanOrBuilder, String propName)
1651         throws IOException
1652     {
1653 
1654         if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
1655             handleIgnoredProperty(p, ctxt, beanOrBuilder, propName);
1656         } else if (_anySetter != null) {
1657             try {
1658                // should we consider return type of any setter?
1659                 _anySetter.deserializeAndSet(p, ctxt, beanOrBuilder, propName);
1660             } catch (Exception e) {
1661                 wrapAndThrow(e, beanOrBuilder, propName, ctxt);
1662             }
1663         } else {
1664             // Unknown: let's call handler method
1665             handleUnknownProperty(p, ctxt, beanOrBuilder, propName);
1666         }
1667     }
1668 
1669     /**
1670      * Method called when a JSON property is encountered that has not matching
1671      * setter, any-setter or field, and thus cannot be assigned.
1672      */
1673     @Override
handleUnknownProperty(JsonParser p, DeserializationContext ctxt, Object beanOrClass, String propName)1674     protected void handleUnknownProperty(JsonParser p, DeserializationContext ctxt,
1675             Object beanOrClass, String propName)
1676         throws IOException
1677     {
1678         if (_ignoreAllUnknown) {
1679             p.skipChildren();
1680             return;
1681         }
1682         if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
1683             handleIgnoredProperty(p, ctxt, beanOrClass, propName);
1684         }
1685         // Otherwise use default handling (call handler(s); if not
1686         // handled, throw exception or skip depending on settings)
1687         super.handleUnknownProperty(p, ctxt, beanOrClass, propName);
1688     }
1689 
1690     /**
1691      * Method called when an explicitly ignored property (one specified with a
1692      * name to match, either by property annotation or class annotation) is encountered.
1693      *
1694      * @since 2.3
1695      */
handleIgnoredProperty(JsonParser p, DeserializationContext ctxt, Object beanOrClass, String propName)1696     protected void handleIgnoredProperty(JsonParser p, DeserializationContext ctxt,
1697             Object beanOrClass, String propName)
1698         throws IOException
1699     {
1700         if (ctxt.isEnabled(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES)) {
1701             throw IgnoredPropertyException.from(p, beanOrClass, propName, getKnownPropertyNames());
1702         }
1703         p.skipChildren();
1704     }
1705 
1706     /**
1707      * Method called in cases where we may have polymorphic deserialization
1708      * case: that is, type of Creator-constructed bean is not the type
1709      * of deserializer itself. It should be a sub-class or implementation
1710      * class; either way, we may have more specific deserializer to use
1711      * for handling it.
1712      *
1713      * @param p (optional) If not null, parser that has more properties to handle
1714      *   (in addition to buffered properties); if null, all properties are passed
1715      *   in buffer
1716      */
1717     @SuppressWarnings("resource")
handlePolymorphic(JsonParser p, DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens)1718     protected Object handlePolymorphic(JsonParser p, DeserializationContext ctxt,
1719             Object bean, TokenBuffer unknownTokens)
1720         throws IOException
1721     {
1722         // First things first: maybe there is a more specific deserializer available?
1723         JsonDeserializer<Object> subDeser = _findSubclassDeserializer(ctxt, bean, unknownTokens);
1724         if (subDeser != null) {
1725             if (unknownTokens != null) {
1726                 // need to add END_OBJECT marker first
1727                 unknownTokens.writeEndObject();
1728                 JsonParser p2 = unknownTokens.asParser();
1729                 p2.nextToken(); // to get to first data field
1730                 bean = subDeser.deserialize(p2, ctxt, bean);
1731             }
1732             // Original parser may also have some leftovers
1733             if (p != null) {
1734                 bean = subDeser.deserialize(p, ctxt, bean);
1735             }
1736             return bean;
1737         }
1738         // nope; need to use this deserializer. Unknowns we've seen so far?
1739         if (unknownTokens != null) {
1740             bean = handleUnknownProperties(ctxt, bean, unknownTokens);
1741         }
1742         // and/or things left to process via main parser?
1743         if (p != null) {
1744             bean = deserialize(p, ctxt, bean);
1745         }
1746         return bean;
1747     }
1748 
1749     /**
1750      * Helper method called to (try to) locate deserializer for given sub-type of
1751      * type that this deserializer handles.
1752      */
_findSubclassDeserializer(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens)1753     protected JsonDeserializer<Object> _findSubclassDeserializer(DeserializationContext ctxt,
1754             Object bean, TokenBuffer unknownTokens)
1755         throws IOException
1756     {
1757         JsonDeserializer<Object> subDeser;
1758 
1759         // First: maybe we have already created sub-type deserializer?
1760         synchronized (this) {
1761             subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass()));
1762         }
1763         if (subDeser != null) {
1764             return subDeser;
1765         }
1766         // If not, maybe we can locate one. First, need provider
1767         JavaType type = ctxt.constructType(bean.getClass());
1768         /* 30-Jan-2012, tatu: Ideally we would be passing referring
1769          *   property; which in theory we could keep track of via
1770          *   ResolvableDeserializer (if we absolutely must...).
1771          *   But for now, let's not bother.
1772          */
1773 //        subDeser = ctxt.findValueDeserializer(type, _property);
1774         subDeser = ctxt.findRootValueDeserializer(type);
1775         // Also, need to cache it
1776         if (subDeser != null) {
1777             synchronized (this) {
1778                 if (_subDeserializers == null) {
1779                     _subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();;
1780                 }
1781                 _subDeserializers.put(new ClassKey(bean.getClass()), subDeser);
1782             }
1783         }
1784         return subDeser;
1785     }
1786 
1787     /*
1788     /**********************************************************
1789     /* Helper methods for error reporting
1790     /**********************************************************
1791      */
1792 
1793     /**
1794      * Method that will modify caught exception (passed in as argument)
1795      * as necessary to include reference information, and to ensure it
1796      * is a subtype of {@link IOException}, or an unchecked exception.
1797      *<p>
1798      * Rules for wrapping and unwrapping are bit complicated; essentially:
1799      *<ul>
1800      * <li>Errors are to be passed as is (if uncovered via unwrapping)
1801      * <li>"Plain" IOExceptions (ones that are not of type
1802      *   {@link JsonMappingException} are to be passed as is
1803      *</ul>
1804      */
wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)1805     public void wrapAndThrow(Throwable t, Object bean, String fieldName, DeserializationContext ctxt)
1806         throws IOException
1807     {
1808         // Need to add reference information
1809         throw JsonMappingException.wrapWithPath(throwOrReturnThrowable(t, ctxt), bean, fieldName);
1810     }
1811 
throwOrReturnThrowable(Throwable t, DeserializationContext ctxt)1812     private Throwable throwOrReturnThrowable(Throwable t, DeserializationContext ctxt)
1813         throws IOException
1814     {
1815         /* 05-Mar-2009, tatu: But one nasty edge is when we get
1816          *   StackOverflow: usually due to infinite loop. But that
1817          *   often gets hidden within an InvocationTargetException...
1818          */
1819         while (t instanceof InvocationTargetException && t.getCause() != null) {
1820             t = t.getCause();
1821         }
1822         // Errors to be passed as is
1823         ClassUtil.throwIfError(t);
1824         boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
1825         // Ditto for IOExceptions; except we may want to wrap JSON exceptions
1826         if (t instanceof IOException) {
1827             if (!wrap || !(t instanceof JsonProcessingException)) {
1828                 throw (IOException) t;
1829             }
1830         } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
1831             ClassUtil.throwIfRTE(t);
1832         }
1833         return t;
1834     }
1835 
wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)1836     protected Object wrapInstantiationProblem(Throwable t, DeserializationContext ctxt)
1837         throws IOException
1838     {
1839         while (t instanceof InvocationTargetException && t.getCause() != null) {
1840             t = t.getCause();
1841         }
1842         // Errors and "plain" IOExceptions to be passed as is
1843         ClassUtil.throwIfError(t);
1844         if (t instanceof IOException) {
1845             // Since we have no more information to add, let's not actually wrap..
1846             throw (IOException) t;
1847         }
1848         boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS);
1849         if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions
1850             ClassUtil.throwIfRTE(t);
1851         }
1852         return ctxt.handleInstantiationProblem(_beanType.getRawClass(), null, t);
1853     }
1854 }
1855