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