• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.databind.deser;
2 
3 import java.io.IOException;
4 import java.util.*;
5 
6 import com.fasterxml.jackson.core.*;
7 import com.fasterxml.jackson.databind.*;
8 import com.fasterxml.jackson.databind.cfg.CoercionAction;
9 import com.fasterxml.jackson.databind.deser.impl.*;
10 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
11 import com.fasterxml.jackson.databind.util.IgnorePropertiesUtil;
12 import com.fasterxml.jackson.databind.util.NameTransformer;
13 import com.fasterxml.jackson.databind.util.TokenBuffer;
14 
15 /**
16  * Deserializer class that can deserialize instances of
17  * arbitrary bean objects, usually from JSON Object structs,
18  */
19 public class BeanDeserializer
20     extends BeanDeserializerBase
21     implements java.io.Serializable
22 {
23     /* TODOs for future versions:
24      *
25      * For 2.9?
26      *
27      * - New method in JsonDeserializer (deserializeNext()) to allow use of more
28      *   efficient 'nextXxx()' method `JsonParser` provides.
29      *
30      * Also: need to ensure efficient impl of those methods for Smile, CBOR
31      * at least (in addition to JSON)
32      */
33 
34     private static final long serialVersionUID = 1L;
35 
36     /**
37      * Lazily constructed exception used as root cause if reporting problem
38      * with creator method that returns <code>null</code> (which is not allowed)
39      *
40      * @since 2.8
41      */
42     protected transient Exception _nullFromCreator;
43 
44     /**
45      * State marker we need in order to avoid infinite recursion for some cases
46      * (not very clean, alas, but has to do for now)
47      *
48      * @since 2.9
49      */
50     private volatile transient NameTransformer _currentlyTransforming;
51 
52     /*
53     /**********************************************************
54     /* Life-cycle, construction, initialization
55     /**********************************************************
56      */
57 
58     /**
59      * Constructor used by {@link BeanDeserializerBuilder}.
60      *
61      * @deprecated in 2.12, remove from 3.0
62      */
63     @Deprecated
BeanDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, HashSet<String> ignorableProps, boolean ignoreAllUnknown, boolean hasViews)64     public BeanDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc,
65             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
66             HashSet<String> ignorableProps, boolean ignoreAllUnknown,
67             boolean hasViews)
68     {
69         super(builder, beanDesc, properties, backRefs,
70                 ignorableProps, ignoreAllUnknown, null, hasViews);
71     }
72 
73     /**
74      * Constructor used by {@link BeanDeserializerBuilder}.
75      *
76      * @since 2.12
77      */
BeanDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, HashSet<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps, boolean hasViews)78     public BeanDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc,
79                             BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs,
80                             HashSet<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps,
81                             boolean hasViews)
82     {
83         super(builder, beanDesc, properties, backRefs,
84                 ignorableProps, ignoreAllUnknown, includableProps, hasViews);
85     }
86 
87     /**
88      * Copy-constructor that can be used by sub-classes to allow
89      * copy-on-write style copying of settings of an existing instance.
90      */
BeanDeserializer(BeanDeserializerBase src)91     protected BeanDeserializer(BeanDeserializerBase src) {
92         super(src, src._ignoreAllUnknown);
93     }
94 
BeanDeserializer(BeanDeserializerBase src, boolean ignoreAllUnknown)95     protected BeanDeserializer(BeanDeserializerBase src, boolean ignoreAllUnknown) {
96         super(src, ignoreAllUnknown);
97     }
98 
BeanDeserializer(BeanDeserializerBase src, NameTransformer unwrapper)99     protected BeanDeserializer(BeanDeserializerBase src, NameTransformer unwrapper) {
100         super(src, unwrapper);
101     }
102 
BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir)103     public BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir) {
104         super(src, oir);
105     }
106 
107     /**
108      * @deprecated in 2.12, remove from 3.0
109      */
110     @Deprecated
BeanDeserializer(BeanDeserializerBase src, Set<String> ignorableProps)111     public BeanDeserializer(BeanDeserializerBase src, Set<String> ignorableProps) {
112         super(src, ignorableProps);
113     }
114 
115     /**
116      * @since 2.12
117      */
BeanDeserializer(BeanDeserializerBase src, Set<String> ignorableProps, Set<String> includableProps)118     public BeanDeserializer(BeanDeserializerBase src, Set<String> ignorableProps, Set<String> includableProps) {
119         super(src, ignorableProps, includableProps);
120     }
121 
BeanDeserializer(BeanDeserializerBase src, BeanPropertyMap props)122     public BeanDeserializer(BeanDeserializerBase src, BeanPropertyMap props) {
123         super(src, props);
124     }
125 
126     @Override
unwrappingDeserializer(NameTransformer transformer)127     public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer transformer)
128     {
129         // bit kludgy but we don't want to accidentally change type; sub-classes
130         // MUST override this method to support unwrapped properties...
131         if (getClass() != BeanDeserializer.class) {
132             return this;
133         }
134         // 25-Mar-2017, tatu: Not clean at all, but for [databind#383] we do need
135         //   to keep track of accidental recursion...
136         if (_currentlyTransforming == transformer) {
137             return this;
138         }
139         _currentlyTransforming = transformer;
140         try {
141             return new BeanDeserializer(this, transformer);
142         } finally { _currentlyTransforming = null; }
143     }
144 
145     @Override
withObjectIdReader(ObjectIdReader oir)146     public BeanDeserializer withObjectIdReader(ObjectIdReader oir) {
147         return new BeanDeserializer(this, oir);
148     }
149 
150     @Override
withByNameInclusion(Set<String> ignorableProps, Set<String> includableProps)151     public BeanDeserializer withByNameInclusion(Set<String> ignorableProps,
152             Set<String> includableProps) {
153         return new BeanDeserializer(this, ignorableProps, includableProps);
154     }
155 
156     @Override
withIgnoreAllUnknown(boolean ignoreUnknown)157     public BeanDeserializerBase withIgnoreAllUnknown(boolean ignoreUnknown) {
158         return new BeanDeserializer(this, ignoreUnknown);
159     }
160 
161     @Override
withBeanProperties(BeanPropertyMap props)162     public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) {
163         return new BeanDeserializer(this, props);
164     }
165 
166     @Override
asArrayDeserializer()167     protected BeanDeserializerBase asArrayDeserializer() {
168         SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder();
169         return new BeanAsArrayDeserializer(this, props);
170     }
171 
172     /*
173     /**********************************************************
174     /* JsonDeserializer implementation
175     /**********************************************************
176      */
177 
178     /**
179      * Main deserialization method for bean-based objects (POJOs).
180      */
181     @Override
deserialize(JsonParser p, DeserializationContext ctxt)182     public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
183     {
184         // common case first
185         if (p.isExpectedStartObjectToken()) {
186             if (_vanillaProcessing) {
187                 return vanillaDeserialize(p, ctxt, p.nextToken());
188             }
189             // 23-Sep-2015, tatu: This is wrong at some many levels, but for now... it is
190             //    what it is, including "expected behavior".
191             p.nextToken();
192             if (_objectIdReader != null) {
193                 return deserializeWithObjectId(p, ctxt);
194             }
195             return deserializeFromObject(p, ctxt);
196         }
197         return _deserializeOther(p, ctxt, p.currentToken());
198     }
199 
_deserializeOther(JsonParser p, DeserializationContext ctxt, JsonToken t)200     protected final Object _deserializeOther(JsonParser p, DeserializationContext ctxt,
201             JsonToken t) throws IOException
202     {
203         // and then others, generally requiring use of @JsonCreator
204         if (t != null) {
205             switch (t) {
206             case VALUE_STRING:
207                 return deserializeFromString(p, ctxt);
208             case VALUE_NUMBER_INT:
209                 return deserializeFromNumber(p, ctxt);
210             case VALUE_NUMBER_FLOAT:
211                 return deserializeFromDouble(p, ctxt);
212             case VALUE_EMBEDDED_OBJECT:
213                 return deserializeFromEmbedded(p, ctxt);
214             case VALUE_TRUE:
215             case VALUE_FALSE:
216                 return deserializeFromBoolean(p, ctxt);
217             case VALUE_NULL:
218                 return deserializeFromNull(p, ctxt);
219             case START_ARRAY:
220                 // these only work if there's a (delegating) creator, or UNWRAP_SINGLE_ARRAY
221                 return _deserializeFromArray(p, ctxt);
222             case FIELD_NAME:
223             case END_OBJECT: // added to resolve [JACKSON-319], possible related issues
224                 if (_vanillaProcessing) {
225                     return vanillaDeserialize(p, ctxt, t);
226                 }
227                 if (_objectIdReader != null) {
228                     return deserializeWithObjectId(p, ctxt);
229                 }
230                 return deserializeFromObject(p, ctxt);
231             default:
232             }
233         }
234         return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
235     }
236 
237     @Deprecated // since 2.8; remove unless getting used
_missingToken(JsonParser p, DeserializationContext ctxt)238     protected Object _missingToken(JsonParser p, DeserializationContext ctxt) throws IOException {
239         throw ctxt.endOfInputException(handledType());
240     }
241 
242     /**
243      * Secondary deserialization method, called in cases where POJO
244      * instance is created as part of deserialization, potentially
245      * after collecting some or all of the properties to set.
246      */
247     @Override
deserialize(JsonParser p, DeserializationContext ctxt, Object bean)248     public Object deserialize(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException
249     {
250         // [databind#631]: Assign current value, to be accessible by custom serializers
251         p.setCurrentValue(bean);
252         if (_injectables != null) {
253             injectValues(ctxt, bean);
254         }
255         if (_unwrappedPropertyHandler != null) {
256             return deserializeWithUnwrapped(p, ctxt, bean);
257         }
258         if (_externalTypeIdHandler != null) {
259             return deserializeWithExternalTypeId(p, ctxt, bean);
260         }
261         String propName;
262 
263         // 23-Mar-2010, tatu: In some cases, we start with full JSON object too...
264         if (p.isExpectedStartObjectToken()) {
265             propName = p.nextFieldName();
266             if (propName == null) {
267                 return bean;
268             }
269         } else {
270             if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
271                 propName = p.currentName();
272             } else {
273                 return bean;
274             }
275         }
276         if (_needViewProcesing) {
277             Class<?> view = ctxt.getActiveView();
278             if (view != null) {
279                 return deserializeWithView(p, ctxt, bean, view);
280             }
281         }
282         do {
283             p.nextToken();
284             SettableBeanProperty prop = _beanProperties.find(propName);
285 
286             if (prop != null) { // normal case
287                 try {
288                     prop.deserializeAndSet(p, ctxt, bean);
289                 } catch (Exception e) {
290                     wrapAndThrow(e, bean, propName, ctxt);
291                 }
292                 continue;
293             }
294             handleUnknownVanilla(p, ctxt, bean, propName);
295         } while ((propName = p.nextFieldName()) != null);
296         return bean;
297     }
298 
299     /*
300     /**********************************************************
301     /* Concrete deserialization methods
302     /**********************************************************
303      */
304 
305     /**
306      * Streamlined version that is only used when no "special"
307      * features are enabled.
308      */
vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t)309     private final Object vanillaDeserialize(JsonParser p,
310     		DeserializationContext ctxt, JsonToken t)
311         throws IOException
312     {
313         final Object bean = _valueInstantiator.createUsingDefault(ctxt);
314         // [databind#631]: Assign current value, to be accessible by custom serializers
315         p.setCurrentValue(bean);
316         if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
317             String propName = p.currentName();
318             do {
319                 p.nextToken();
320                 SettableBeanProperty prop = _beanProperties.find(propName);
321 
322                 if (prop != null) { // normal case
323                     try {
324                         prop.deserializeAndSet(p, ctxt, bean);
325                     } catch (Exception e) {
326                         wrapAndThrow(e, bean, propName, ctxt);
327                     }
328                     continue;
329                 }
330                 handleUnknownVanilla(p, ctxt, bean, propName);
331             } while ((propName = p.nextFieldName()) != null);
332         }
333         return bean;
334     }
335 
336     /**
337      * General version used when handling needs more advanced features.
338      */
339     @Override
deserializeFromObject(JsonParser p, DeserializationContext ctxt)340     public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException
341     {
342         /* 09-Dec-2014, tatu: As per [databind#622], we need to allow Object Id references
343          *   to come in as JSON Objects as well; but for now assume they will
344          *   be simple, single-property references, which means that we can
345          *   recognize them without having to buffer anything.
346          *   Once again, if we must, we can do more complex handling with buffering,
347          *   but let's only do that if and when that becomes necessary.
348          */
349         if ((_objectIdReader != null) && _objectIdReader.maySerializeAsObject()) {
350             if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)
351                     && _objectIdReader.isValidReferencePropertyName(p.currentName(), p)) {
352                 return deserializeFromObjectId(p, ctxt);
353             }
354         }
355         if (_nonStandardCreation) {
356             if (_unwrappedPropertyHandler != null) {
357                 return deserializeWithUnwrapped(p, ctxt);
358             }
359             if (_externalTypeIdHandler != null) {
360                 return deserializeWithExternalTypeId(p, ctxt);
361             }
362             Object bean = deserializeFromObjectUsingNonDefault(p, ctxt);
363             /* 27-May-2014, tatu: I don't think view processing would work
364              *   at this point, so commenting it out; but leaving in place
365              *   just in case I forgot something fundamental...
366              */
367             /*
368             if (_needViewProcesing) {
369                 Class<?> view = ctxt.getActiveView();
370                 if (view != null) {
371                     return deserializeWithView(p, ctxt, bean, view);
372                 }
373             }
374             */
375             return bean;
376         }
377         final Object bean = _valueInstantiator.createUsingDefault(ctxt);
378         // [databind#631]: Assign current value, to be accessible by custom deserializers
379         p.setCurrentValue(bean);
380         if (p.canReadObjectId()) {
381             Object id = p.getObjectId();
382             if (id != null) {
383                 _handleTypedObjectId(p, ctxt, bean, id);
384             }
385         }
386         if (_injectables != null) {
387             injectValues(ctxt, bean);
388         }
389         if (_needViewProcesing) {
390             Class<?> view = ctxt.getActiveView();
391             if (view != null) {
392                 return deserializeWithView(p, ctxt, bean, view);
393             }
394         }
395         if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
396             String propName = p.currentName();
397             do {
398                 p.nextToken();
399                 SettableBeanProperty prop = _beanProperties.find(propName);
400                 if (prop != null) { // normal case
401                     try {
402                         prop.deserializeAndSet(p, ctxt, bean);
403                     } catch (Exception e) {
404                         wrapAndThrow(e, bean, propName, ctxt);
405                     }
406                     continue;
407                 }
408                 handleUnknownVanilla(p, ctxt, bean, propName);
409             } while ((propName = p.nextFieldName()) != null);
410         }
411         return bean;
412     }
413 
414     /**
415      * Method called to deserialize bean using "property-based creator":
416      * this means that a non-default constructor or factory method is
417      * called, and then possibly other setters. The trick is that
418      * values for creator method need to be buffered, first; and
419      * due to non-guaranteed ordering possibly some other properties
420      * as well.
421      */
422     @Override
423     @SuppressWarnings("resource")
_deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt)424     protected Object _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt)
425         throws IOException
426     {
427         final PropertyBasedCreator creator = _propertyBasedCreator;
428         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
429         TokenBuffer unknown = null;
430         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
431 
432         JsonToken t = p.currentToken();
433         List<BeanReferring> referrings = null;
434         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
435             String propName = p.currentName();
436             p.nextToken(); // to point to value
437             // Object Id property?
438             if (buffer.readIdProperty(propName)) {
439                 continue;
440             }
441             // creator property?
442             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
443             if (creatorProp != null) {
444                 // Last creator property to set?
445                 Object value;
446                 if ((activeView != null) && !creatorProp.visibleInView(activeView)) {
447                     p.skipChildren();
448                     continue;
449                 }
450                 value = _deserializeWithErrorWrapping(p, ctxt, creatorProp);
451                 if (buffer.assignParameter(creatorProp, value)) {
452                     p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
453                     Object bean;
454                     try {
455                         bean = creator.build(ctxt, buffer);
456                     } catch (Exception e) {
457                         bean = wrapInstantiationProblem(e, ctxt);
458                     }
459                     if (bean == null) {
460                         return ctxt.handleInstantiationProblem(handledType(), null,
461                                 _creatorReturnedNullException());
462                     }
463                     // [databind#631]: Assign current value, to be accessible by custom serializers
464                     p.setCurrentValue(bean);
465 
466                     //  polymorphic?
467                     if (bean.getClass() != _beanType.getRawClass()) {
468                         return handlePolymorphic(p, ctxt, bean, unknown);
469                     }
470                     if (unknown != null) { // nope, just extra unknown stuff...
471                         bean = handleUnknownProperties(ctxt, bean, unknown);
472                     }
473                     // or just clean?
474                     return deserialize(p, ctxt, bean);
475                 }
476                 continue;
477             }
478             // regular property? needs buffering
479             SettableBeanProperty prop = _beanProperties.find(propName);
480             if (prop != null) {
481                 try {
482                     buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop));
483                 } catch (UnresolvedForwardReference reference) {
484                     // 14-Jun-2016, tatu: As per [databind#1261], looks like we need additional
485                     //    handling of forward references here. Not exactly sure why existing
486                     //    facilities did not cover, but this does appear to solve the problem
487                     BeanReferring referring = handleUnresolvedReference(ctxt,
488                             prop, buffer, reference);
489                     if (referrings == null) {
490                         referrings = new ArrayList<BeanReferring>();
491                     }
492                     referrings.add(referring);
493                 }
494                 continue;
495             }
496             // Things marked as ignorable should not be passed to any setter
497             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
498                 handleIgnoredProperty(p, ctxt, handledType(), propName);
499                 continue;
500             }
501             // "any property"?
502             if (_anySetter != null) {
503                 try {
504                     buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt));
505                 } catch (Exception e) {
506                     wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
507                 }
508                 continue;
509             }
510             // Ok then, let's collect the whole field; name and value
511             if (unknown == null) {
512                 unknown = new TokenBuffer(p, ctxt);
513             }
514             unknown.writeFieldName(propName);
515             unknown.copyCurrentStructure(p);
516         }
517 
518         // We hit END_OBJECT, so:
519         Object bean;
520         try {
521             bean = creator.build(ctxt, buffer);
522         } catch (Exception e) {
523             wrapInstantiationProblem(e, ctxt);
524             bean = null; // never gets here
525         }
526         // 13-Apr-2020, tatu: [databind#2678] need to handle injection here
527         if (_injectables != null) {
528             injectValues(ctxt, bean);
529         }
530 
531         if (referrings != null) {
532             for (BeanReferring referring : referrings) {
533                referring.setBean(bean);
534             }
535         }
536         if (unknown != null) {
537             // polymorphic?
538             if (bean.getClass() != _beanType.getRawClass()) {
539                 return handlePolymorphic(null, ctxt, bean, unknown);
540             }
541             // no, just some extra unknown properties
542             return handleUnknownProperties(ctxt, bean, unknown);
543         }
544         return bean;
545     }
546 
547     /**
548      * @since 2.8
549      */
handleUnresolvedReference(DeserializationContext ctxt, SettableBeanProperty prop, PropertyValueBuffer buffer, UnresolvedForwardReference reference)550     private BeanReferring handleUnresolvedReference(DeserializationContext ctxt,
551             SettableBeanProperty prop, PropertyValueBuffer buffer,
552             UnresolvedForwardReference reference)
553         throws JsonMappingException
554     {
555         BeanReferring referring = new BeanReferring(ctxt, reference,
556                 prop.getType(), buffer, prop);
557         reference.getRoid().appendReferring(referring);
558         return referring;
559     }
560 
_deserializeWithErrorWrapping(JsonParser p, DeserializationContext ctxt, SettableBeanProperty prop)561     protected final Object _deserializeWithErrorWrapping(JsonParser p,
562             DeserializationContext ctxt, SettableBeanProperty prop)
563         throws IOException
564     {
565         try {
566             return prop.deserialize(p, ctxt);
567         } catch (Exception e) {
568             wrapAndThrow(e, _beanType.getRawClass(), prop.getName(), ctxt);
569             // never gets here, unless caller declines to throw an exception
570             return null;
571         }
572     }
573 
574     /**
575      * Helper method called for rare case of pointing to {@link JsonToken#VALUE_NULL}
576      * token. While this is most often an erroneous condition, there is one specific
577      * case with XML handling where polymorphic type with no properties is exposed
578      * as such, and should be handled same as empty Object.
579      *
580      * @since 2.7
581      */
deserializeFromNull(JsonParser p, DeserializationContext ctxt)582     protected Object deserializeFromNull(JsonParser p, DeserializationContext ctxt)
583         throws IOException
584     {
585         // 17-Dec-2015, tatu: Highly specialized case, mainly to support polymorphic
586         //   "empty" POJOs deserialized from XML, where empty XML tag synthesizes a
587         //   `VALUE_NULL` token.
588         if (p.requiresCustomCodec()) { // not only XML module, but mostly it...
589             @SuppressWarnings("resource")
590             TokenBuffer tb = new TokenBuffer(p, ctxt);
591             tb.writeEndObject();
592             JsonParser p2 = tb.asParser(p);
593             p2.nextToken(); // to point to END_OBJECT
594             // note: don't have ObjectId to consider at this point, so:
595             Object ob = _vanillaProcessing ? vanillaDeserialize(p2, ctxt, JsonToken.END_OBJECT)
596                     : deserializeFromObject(p2, ctxt);
597             p2.close();
598             return ob;
599         }
600         return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
601     }
602 
603     @Override
_deserializeFromArray(JsonParser p, DeserializationContext ctxt)604     protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException
605     {
606         // note: cannot call `_delegateDeserializer()` since order reversed here:
607         JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer;
608         // fallback to non-array delegate
609         if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) {
610             Object bean = _valueInstantiator.createUsingArrayDelegate(ctxt,
611                     delegateDeser.deserialize(p, ctxt));
612             if (_injectables != null) {
613                 injectValues(ctxt, bean);
614             }
615             return bean;
616         }
617         final CoercionAction act = _findCoercionFromEmptyArray(ctxt);
618         final boolean unwrap = ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS);
619 
620         if (unwrap || (act != CoercionAction.Fail)) {
621             JsonToken t = p.nextToken();
622             if (t == JsonToken.END_ARRAY) {
623                 switch (act) {
624                 case AsEmpty:
625                     return getEmptyValue(ctxt);
626                 case AsNull:
627                 case TryConvert:
628                     return getNullValue(ctxt);
629                 default:
630                 }
631                 return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null);
632             }
633             if (unwrap) {
634                 final Object value = deserialize(p, ctxt);
635                 if (p.nextToken() != JsonToken.END_ARRAY) {
636                     handleMissingEndArrayForSingle(p, ctxt);
637                 }
638                 return value;
639             }
640         }
641         return ctxt.handleUnexpectedToken(getValueType(ctxt), p);
642     }
643 
644     /*
645     /**********************************************************
646     /* Deserializing when we have to consider an active View
647     /**********************************************************
648      */
649 
deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class<?> activeView)650     protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
651             Object bean, Class<?> activeView)
652         throws IOException
653     {
654         if (p.hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
655             String propName = p.currentName();
656             do {
657                 p.nextToken();
658                 // TODO: 06-Jan-2015, tatu: try streamlining call sequences here as well
659                 SettableBeanProperty prop = _beanProperties.find(propName);
660                 if (prop != null) {
661                     if (!prop.visibleInView(activeView)) {
662                         p.skipChildren();
663                         continue;
664                     }
665                     try {
666                         prop.deserializeAndSet(p, ctxt, bean);
667                     } catch (Exception e) {
668                         wrapAndThrow(e, bean, propName, ctxt);
669                     }
670                     continue;
671                 }
672                 handleUnknownVanilla(p, ctxt, bean, propName);
673             } while ((propName = p.nextFieldName()) != null);
674         }
675         return bean;
676     }
677 
678     /*
679     /**********************************************************
680     /* Handling for cases where we have "unwrapped" values
681     /**********************************************************
682      */
683 
684     /**
685      * Method called when there are declared "unwrapped" properties
686      * which need special handling
687      */
688     @SuppressWarnings("resource")
deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)689     protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)
690         throws IOException
691     {
692         if (_delegateDeserializer != null) {
693             return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt));
694         }
695         if (_propertyBasedCreator != null) {
696             return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt);
697         }
698         TokenBuffer tokens = new TokenBuffer(p, ctxt);
699         tokens.writeStartObject();
700         final Object bean = _valueInstantiator.createUsingDefault(ctxt);
701 
702         // [databind#631]: Assign current value, to be accessible by custom serializers
703         p.setCurrentValue(bean);
704 
705         if (_injectables != null) {
706             injectValues(ctxt, bean);
707         }
708         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
709         String propName = p.hasTokenId(JsonTokenId.ID_FIELD_NAME) ? p.currentName() : null;
710 
711         for (; propName != null; propName = p.nextFieldName()) {
712             p.nextToken();
713             SettableBeanProperty prop = _beanProperties.find(propName);
714             if (prop != null) { // normal case
715                 if ((activeView != null) && !prop.visibleInView(activeView)) {
716                     p.skipChildren();
717                     continue;
718                 }
719                 try {
720                     prop.deserializeAndSet(p, ctxt, bean);
721                 } catch (Exception e) {
722                     wrapAndThrow(e, bean, propName, ctxt);
723                 }
724                 continue;
725             }
726             // Things marked as ignorable should not be passed to any setter
727             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
728                 handleIgnoredProperty(p, ctxt, bean, propName);
729                 continue;
730             }
731             // 29-Nov-2016, tatu: probably should try to avoid sending content
732             //    both to any setter AND buffer... but, for now, the only thing
733             //    we can do.
734             // how about any setter? We'll get copies but...
735             if (_anySetter == null) {
736                 // but... others should be passed to unwrapped property deserializers
737                 tokens.writeFieldName(propName);
738                 tokens.copyCurrentStructure(p);
739                 continue;
740             }
741             // Need to copy to a separate buffer first
742             TokenBuffer b2 = TokenBuffer.asCopyOfValue(p);
743             tokens.writeFieldName(propName);
744             tokens.append(b2);
745             try {
746                 _anySetter.deserializeAndSet(b2.asParserOnFirstToken(), ctxt, bean, propName);
747             } catch (Exception e) {
748                 wrapAndThrow(e, bean, propName, ctxt);
749             }
750         }
751         tokens.writeEndObject();
752         _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
753         return bean;
754     }
755 
756     @SuppressWarnings("resource")
deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object bean)757     protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt,
758             Object bean)
759         throws IOException
760     {
761         JsonToken t = p.currentToken();
762         if (t == JsonToken.START_OBJECT) {
763             t = p.nextToken();
764         }
765         TokenBuffer tokens = new TokenBuffer(p, ctxt);
766         tokens.writeStartObject();
767         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
768         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
769             String propName = p.currentName();
770             SettableBeanProperty prop = _beanProperties.find(propName);
771             p.nextToken();
772             if (prop != null) { // normal case
773                 if (activeView != null && !prop.visibleInView(activeView)) {
774                     p.skipChildren();
775                     continue;
776                 }
777                 try {
778                     prop.deserializeAndSet(p, ctxt, bean);
779                 } catch (Exception e) {
780                     wrapAndThrow(e, bean, propName, ctxt);
781                 }
782                 continue;
783             }
784             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
785                 handleIgnoredProperty(p, ctxt, bean, propName);
786                 continue;
787             }
788             // 29-Nov-2016, tatu: probably should try to avoid sending content
789             //    both to any setter AND buffer... but, for now, the only thing
790             //    we can do.
791             // how about any setter? We'll get copies but...
792             if (_anySetter == null) {
793                 // but... others should be passed to unwrapped property deserializers
794                 tokens.writeFieldName(propName);
795                 tokens.copyCurrentStructure(p);
796             } else {
797                 // Need to copy to a separate buffer first
798                 TokenBuffer b2 = TokenBuffer.asCopyOfValue(p);
799                 tokens.writeFieldName(propName);
800                 tokens.append(b2);
801                 try {
802                     _anySetter.deserializeAndSet(b2.asParserOnFirstToken(), ctxt, bean, propName);
803                 } catch (Exception e) {
804                     wrapAndThrow(e, bean, propName, ctxt);
805                 }
806                 continue;
807             }
808         }
809         tokens.writeEndObject();
810         _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
811         return bean;
812     }
813 
814     @SuppressWarnings("resource")
deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt)815     protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt)
816         throws IOException
817     {
818         // 01-Dec-2016, tatu: Note: This IS legal to call, but only when unwrapped
819         //    value itself is NOT passed via `CreatorProperty` (which isn't supported).
820         //    Ok however to pass via setter or field.
821 
822         final PropertyBasedCreator creator = _propertyBasedCreator;
823         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
824 
825         TokenBuffer tokens = new TokenBuffer(p, ctxt);
826         tokens.writeStartObject();
827 
828         JsonToken t = p.currentToken();
829         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
830             String propName = p.currentName();
831             p.nextToken(); // to point to value
832             // creator property?
833             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
834             if (creatorProp != null) {
835                 // Last creator property to set?
836                 if (buffer.assignParameter(creatorProp,
837                         _deserializeWithErrorWrapping(p, ctxt, creatorProp))) {
838                     t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
839                     Object bean;
840                     try {
841                         bean = creator.build(ctxt, buffer);
842                     } catch (Exception e) {
843                         bean = wrapInstantiationProblem(e, ctxt);
844                     }
845                     // [databind#631]: Assign current value, to be accessible by custom serializers
846                     p.setCurrentValue(bean);
847                     // if so, need to copy all remaining tokens into buffer
848                     while (t == JsonToken.FIELD_NAME) {
849                         // NOTE: do NOT skip name as it needs to be copied; `copyCurrentStructure` does that
850                         tokens.copyCurrentStructure(p);
851                         t = p.nextToken();
852                     }
853                     // 28-Aug-2018, tatu: Let's add sanity check here, easier to catch off-by-some
854                     //    problems if we maintain invariants
855                     if (t != JsonToken.END_OBJECT) {
856                         ctxt.reportWrongTokenException(this, JsonToken.END_OBJECT,
857                                 "Attempted to unwrap '%s' value",
858                                 handledType().getName());
859                     }
860                     tokens.writeEndObject();
861                     if (bean.getClass() != _beanType.getRawClass()) {
862                         // !!! 08-Jul-2011, tatu: Could probably support; but for now
863                         //   it's too complicated, so bail out
864                         ctxt.reportInputMismatch(creatorProp,
865                                 "Cannot create polymorphic instances with unwrapped values");
866                         return null;
867                     }
868                     return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
869                 }
870                 continue;
871             }
872             // Object Id property?
873             if (buffer.readIdProperty(propName)) {
874                 continue;
875             }
876             // regular property? needs buffering
877             SettableBeanProperty prop = _beanProperties.find(propName);
878             if (prop != null) {
879                 buffer.bufferProperty(prop, _deserializeWithErrorWrapping(p, ctxt, prop));
880                 continue;
881             }
882             // Things marked as ignorable should not be passed to any setter
883             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
884                 handleIgnoredProperty(p, ctxt, handledType(), propName);
885                 continue;
886             }
887             // 29-Nov-2016, tatu: probably should try to avoid sending content
888             //    both to any setter AND buffer... but, for now, the only thing
889             //    we can do.
890             // how about any setter? We'll get copies but...
891             if (_anySetter == null) {
892                 // but... others should be passed to unwrapped property deserializers
893                 tokens.writeFieldName(propName);
894                 tokens.copyCurrentStructure(p);
895             } else {
896                 // Need to copy to a separate buffer first
897                 TokenBuffer b2 = TokenBuffer.asCopyOfValue(p);
898                 tokens.writeFieldName(propName);
899                 tokens.append(b2);
900                 try {
901                     buffer.bufferAnyProperty(_anySetter, propName,
902                             _anySetter.deserialize(b2.asParserOnFirstToken(), ctxt));
903                 } catch (Exception e) {
904                     wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
905                 }
906                 continue;
907             }
908         }
909 
910         // We hit END_OBJECT, so:
911         Object bean;
912         try {
913             bean = creator.build(ctxt, buffer);
914         } catch (Exception e) {
915             wrapInstantiationProblem(e, ctxt);
916             return null; // never gets here
917         }
918         return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens);
919     }
920 
921     /*
922     /**********************************************************
923     /* Handling for cases where we have property/-ies with
924     /* external type id
925     /**********************************************************
926      */
927 
deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)928     protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
929         throws IOException
930     {
931         if (_propertyBasedCreator != null) {
932             return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt);
933         }
934         if (_delegateDeserializer != null) {
935             /* 24-Nov-2015, tatu: Use of delegating creator needs to have precedence, and basically
936              *   external type id handling just has to be ignored, as they would relate to target
937              *   type and not delegate type. Whether this works as expected is another story, but
938              *   there's no other way to really mix these conflicting features.
939              */
940             return _valueInstantiator.createUsingDelegate(ctxt,
941                     _delegateDeserializer.deserialize(p, ctxt));
942         }
943 
944         return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt));
945     }
946 
deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean)947     protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt,
948             Object bean)
949         throws IOException
950     {
951         final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
952         final ExternalTypeHandler ext = _externalTypeIdHandler.start();
953 
954         for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) {
955             String propName = p.currentName();
956             t = p.nextToken();
957             SettableBeanProperty prop = _beanProperties.find(propName);
958             if (prop != null) { // normal case
959                 // [JACKSON-831]: may have property AND be used as external type id:
960                 if (t.isScalarValue()) {
961                     ext.handleTypePropertyValue(p, ctxt, propName, bean);
962                 }
963                 if (activeView != null && !prop.visibleInView(activeView)) {
964                     p.skipChildren();
965                     continue;
966                 }
967                 try {
968                     prop.deserializeAndSet(p, ctxt, bean);
969                 } catch (Exception e) {
970                     wrapAndThrow(e, bean, propName, ctxt);
971                 }
972                 continue;
973             }
974             // ignorable things should be ignored
975             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
976                 handleIgnoredProperty(p, ctxt, bean, propName);
977                 continue;
978             }
979             // but others are likely to be part of external type id thingy...
980             if (ext.handlePropertyValue(p, ctxt, propName, bean)) {
981                 continue;
982             }
983             // if not, the usual fallback handling:
984             if (_anySetter != null) {
985                 try {
986                     _anySetter.deserializeAndSet(p, ctxt, bean, propName);
987                 } catch (Exception e) {
988                     wrapAndThrow(e, bean, propName, ctxt);
989                 }
990                 continue;
991             }
992             // Unknown: let's call handler method
993             handleUnknownProperty(p, ctxt, bean, propName);
994         }
995         // and when we get this far, let's try finalizing the deal:
996         return ext.complete(p, ctxt, bean);
997     }
998 
999     @SuppressWarnings("resource")
deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt)1000     protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
1001         throws IOException
1002     {
1003         final ExternalTypeHandler ext = _externalTypeIdHandler.start();
1004         final PropertyBasedCreator creator = _propertyBasedCreator;
1005         PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
1006 
1007         TokenBuffer tokens = new TokenBuffer(p, ctxt);
1008         tokens.writeStartObject();
1009 
1010         JsonToken t = p.currentToken();
1011         for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
1012             String propName = p.currentName();
1013             p.nextToken(); // to point to value
1014             // creator property?
1015             SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
1016             if (creatorProp != null) {
1017                 // first: let's check to see if this might be part of value with external type id:
1018                 // 11-Sep-2015, tatu: Important; do NOT pass buffer as last arg, but null,
1019                 //   since it is not the bean
1020                 if (ext.handlePropertyValue(p, ctxt, propName, null)) {
1021                     ;
1022                 } else {
1023                     // Last creator property to set?
1024                     if (buffer.assignParameter(creatorProp, _deserializeWithErrorWrapping(p, ctxt, creatorProp))) {
1025                         t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
1026                         Object bean;
1027                         try {
1028                             bean = creator.build(ctxt, buffer);
1029                         } catch (Exception e) {
1030                             wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
1031                             continue; // never gets here
1032                         }
1033                         // if so, need to copy all remaining tokens into buffer
1034                         while (t == JsonToken.FIELD_NAME) {
1035                             p.nextToken(); // to skip name
1036                             tokens.copyCurrentStructure(p);
1037                             t = p.nextToken();
1038                         }
1039                         if (bean.getClass() != _beanType.getRawClass()) {
1040                             // !!! 08-Jul-2011, tatu: Could theoretically support; but for now
1041                             //   it's too complicated, so bail out
1042                             return ctxt.reportBadDefinition(_beanType, String.format(
1043                                     "Cannot create polymorphic instances with external type ids (%s -> %s)",
1044                                     _beanType, bean.getClass()));
1045                         }
1046                         return ext.complete(p, ctxt, bean);
1047                     }
1048                 }
1049                 continue;
1050             }
1051             // Object Id property?
1052             if (buffer.readIdProperty(propName)) {
1053                 continue;
1054             }
1055             // regular property? needs buffering
1056             SettableBeanProperty prop = _beanProperties.find(propName);
1057             if (prop != null) {
1058                 buffer.bufferProperty(prop, prop.deserialize(p, ctxt));
1059                 continue;
1060             }
1061             // external type id (or property that depends on it)?
1062             if (ext.handlePropertyValue(p, ctxt, propName, null)) {
1063                 continue;
1064             }
1065             // Things marked as ignorable should not be passed to any setter
1066             if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) {
1067                 handleIgnoredProperty(p, ctxt, handledType(), propName);
1068                 continue;
1069             }
1070             // "any property"?
1071             if (_anySetter != null) {
1072                 buffer.bufferAnyProperty(_anySetter, propName,
1073                         _anySetter.deserialize(p, ctxt));
1074                 continue;
1075             }
1076             // Unknown: let's call handler method
1077             handleUnknownProperty(p, ctxt, _valueClass, propName);
1078         }
1079         tokens.writeEndObject();
1080 
1081         // We hit END_OBJECT; resolve the pieces:
1082         try {
1083             return ext.complete(p, ctxt, buffer, creator);
1084         } catch (Exception e) {
1085             return wrapInstantiationProblem(e, ctxt);
1086         }
1087     }
1088 
1089     /**
1090      * Helper method for getting a lazily construct exception to be reported
1091      * to {@link DeserializationContext#handleInstantiationProblem(Class, Object, Throwable)}.
1092      *
1093      * @since 2.8
1094      */
_creatorReturnedNullException()1095     protected Exception _creatorReturnedNullException() {
1096         if (_nullFromCreator == null) {
1097             _nullFromCreator = new NullPointerException("JSON Creator returned null");
1098         }
1099         return _nullFromCreator;
1100     }
1101 
1102     /**
1103      * @since 2.8
1104      */
1105     static class BeanReferring extends Referring
1106     {
1107         private final DeserializationContext _context;
1108         private final SettableBeanProperty _prop;
1109         private Object _bean;
1110 
BeanReferring(DeserializationContext ctxt, UnresolvedForwardReference ref, JavaType valueType, PropertyValueBuffer buffer, SettableBeanProperty prop)1111         BeanReferring(DeserializationContext ctxt, UnresolvedForwardReference ref,
1112                 JavaType valueType, PropertyValueBuffer buffer, SettableBeanProperty prop)
1113         {
1114             super(ref, valueType);
1115             _context = ctxt;
1116             _prop = prop;
1117         }
1118 
setBean(Object bean)1119         public void setBean(Object bean) {
1120             _bean = bean;
1121         }
1122 
1123         @Override
handleResolvedForwardReference(Object id, Object value)1124         public void handleResolvedForwardReference(Object id, Object value) throws IOException
1125         {
1126             if (_bean == null) {
1127                 _context.reportInputMismatch(_prop,
1128 "Cannot resolve ObjectId forward reference using property '%s' (of type %s): Bean not yet resolved",
1129 _prop.getName(), _prop.getDeclaringClass().getName());
1130         }
1131             _prop.set(_bean, value);
1132         }
1133     }
1134 }
1135