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