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.introspect.AnnotatedMethod; 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 * Class that handles deserialization using a separate 17 * Builder class, which is used for data binding and 18 * produces actual deserialized value at the end 19 * of data binding. 20 *<p> 21 * Note on implementation: much of code has been copied from 22 * {@link BeanDeserializer}; there may be opportunities to 23 * refactor this in future. 24 */ 25 public class BuilderBasedDeserializer 26 extends BeanDeserializerBase 27 { 28 private static final long serialVersionUID = 1L; 29 30 protected final AnnotatedMethod _buildMethod; 31 32 /** 33 * Type that the builder will produce, target type; as opposed to 34 * `handledType()` which refers to Builder class. 35 * 36 * @since 2.9 37 */ 38 protected final JavaType _targetType; 39 40 /* 41 /********************************************************** 42 /* Life-cycle, construction, initialization 43 /********************************************************** 44 */ 45 46 /** 47 * Constructor used by {@link BeanDeserializerBuilder}. 48 */ BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, JavaType targetType, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, boolean hasViews)49 public BuilderBasedDeserializer(BeanDeserializerBuilder builder, 50 BeanDescription beanDesc, JavaType targetType, 51 BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, 52 Set<String> ignorableProps, boolean ignoreAllUnknown, 53 boolean hasViews) 54 { 55 this(builder, beanDesc, targetType, properties, backRefs, ignorableProps, ignoreAllUnknown, null, hasViews); 56 } 57 58 /** 59 * @since 2.12 60 */ BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, JavaType targetType, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps, boolean hasViews)61 public BuilderBasedDeserializer(BeanDeserializerBuilder builder, 62 BeanDescription beanDesc, JavaType targetType, 63 BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, 64 Set<String> ignorableProps, boolean ignoreAllUnknown, Set<String> includableProps, 65 boolean hasViews) 66 { 67 super(builder, beanDesc, properties, backRefs, 68 ignorableProps, ignoreAllUnknown, includableProps, hasViews); 69 _targetType = targetType; 70 _buildMethod = builder.getBuildMethod(); 71 // 05-Mar-2012, tatu: Cannot really make Object Ids work with builders, not yet anyway 72 if (_objectIdReader != null) { 73 throw new IllegalArgumentException("Cannot use Object Id with Builder-based deserialization (type " 74 +beanDesc.getType()+")"); 75 } 76 } 77 78 /** 79 * @deprecated Since 2.9 80 */ 81 @Deprecated BuilderBasedDeserializer(BeanDeserializerBuilder builder, BeanDescription beanDesc, BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, Set<String> ignorableProps, boolean ignoreAllUnknown, boolean hasViews)82 public BuilderBasedDeserializer(BeanDeserializerBuilder builder, 83 BeanDescription beanDesc, 84 BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, 85 Set<String> ignorableProps, boolean ignoreAllUnknown, 86 boolean hasViews) 87 { 88 this(builder, beanDesc, 89 beanDesc.getType(), // Wrong! But got no access via `BeanDeserializerBuilder` 90 properties, backRefs, ignorableProps, ignoreAllUnknown, hasViews); 91 } 92 93 /** 94 * Copy-constructor that can be used by sub-classes to allow 95 * copy-on-write styling copying of settings of an existing instance. 96 */ BuilderBasedDeserializer(BuilderBasedDeserializer src)97 protected BuilderBasedDeserializer(BuilderBasedDeserializer src) 98 { 99 this(src, src._ignoreAllUnknown); 100 } 101 BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreAllUnknown)102 protected BuilderBasedDeserializer(BuilderBasedDeserializer src, boolean ignoreAllUnknown) 103 { 104 super(src, ignoreAllUnknown); 105 _buildMethod = src._buildMethod; 106 _targetType = src._targetType; 107 } 108 BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper)109 protected BuilderBasedDeserializer(BuilderBasedDeserializer src, NameTransformer unwrapper) { 110 super(src, unwrapper); 111 _buildMethod = src._buildMethod; 112 _targetType = src._targetType; 113 } 114 BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir)115 public BuilderBasedDeserializer(BuilderBasedDeserializer src, ObjectIdReader oir) { 116 super(src, oir); 117 _buildMethod = src._buildMethod; 118 _targetType = src._targetType; 119 } 120 BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps)121 public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps) { 122 this(src, ignorableProps, src._includableProps); 123 } 124 BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps, Set<String> includableProps)125 public BuilderBasedDeserializer(BuilderBasedDeserializer src, Set<String> ignorableProps, Set<String> includableProps) { 126 super(src, ignorableProps, includableProps); 127 _buildMethod = src._buildMethod; 128 _targetType = src._targetType; 129 } 130 BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props)131 public BuilderBasedDeserializer(BuilderBasedDeserializer src, BeanPropertyMap props) { 132 super(src, props); 133 _buildMethod = src._buildMethod; 134 _targetType = src._targetType; 135 } 136 137 @Override unwrappingDeserializer(NameTransformer unwrapper)138 public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper) 139 { 140 /* main thing really is to just enforce ignoring of unknown 141 * properties; since there may be multiple unwrapped values 142 * and properties for all may be interleaved... 143 */ 144 return new BuilderBasedDeserializer(this, unwrapper); 145 } 146 147 @Override withObjectIdReader(ObjectIdReader oir)148 public BeanDeserializerBase withObjectIdReader(ObjectIdReader oir) { 149 return new BuilderBasedDeserializer(this, oir); 150 } 151 152 @Override withByNameInclusion(Set<String> ignorableProps, Set<String> includableProps)153 public BeanDeserializerBase withByNameInclusion(Set<String> ignorableProps, 154 Set<String> includableProps) { 155 return new BuilderBasedDeserializer(this, ignorableProps, includableProps); 156 } 157 158 @Override withIgnoreAllUnknown(boolean ignoreUnknown)159 public BeanDeserializerBase withIgnoreAllUnknown(boolean ignoreUnknown) { 160 return new BuilderBasedDeserializer(this, ignoreUnknown); 161 } 162 163 @Override withBeanProperties(BeanPropertyMap props)164 public BeanDeserializerBase withBeanProperties(BeanPropertyMap props) { 165 return new BuilderBasedDeserializer(this, props); 166 } 167 168 @Override asArrayDeserializer()169 protected BeanDeserializerBase asArrayDeserializer() { 170 SettableBeanProperty[] props = _beanProperties.getPropertiesInInsertionOrder(); 171 return new BeanAsArrayBuilderDeserializer(this, _targetType, props, _buildMethod); 172 } 173 174 /* 175 /********************************************************** 176 /* JsonDeserializer implementation 177 /********************************************************** 178 */ 179 180 @Override // since 2.9 supportsUpdate(DeserializationConfig config)181 public Boolean supportsUpdate(DeserializationConfig config) { 182 // 26-Oct-2016, tatu: No, we can't merge Builder-based POJOs as of now 183 return Boolean.FALSE; 184 } 185 186 /* 187 /********************************************************** 188 /* JsonDeserializer implementation 189 /********************************************************** 190 */ 191 finishBuild(DeserializationContext ctxt, Object builder)192 protected Object finishBuild(DeserializationContext ctxt, Object builder) 193 throws IOException 194 { 195 // As per [databind#777], allow returning builder itself 196 if (null == _buildMethod) { 197 return builder; 198 } 199 try { 200 return _buildMethod.getMember().invoke(builder, (Object[]) null); 201 } catch (Exception e) { 202 return wrapInstantiationProblem(e, ctxt); 203 } 204 } 205 206 /** 207 * Main deserialization method for bean-based objects (POJOs). 208 */ 209 @Override deserialize(JsonParser p, DeserializationContext ctxt)210 public Object deserialize(JsonParser p, DeserializationContext ctxt) 211 throws IOException 212 { 213 // common case first: 214 if (p.isExpectedStartObjectToken()) { 215 JsonToken t = p.nextToken(); 216 if (_vanillaProcessing) { 217 return finishBuild(ctxt, vanillaDeserialize(p, ctxt, t)); 218 } 219 return finishBuild(ctxt, deserializeFromObject(p, ctxt)); 220 } 221 // and then others, generally requiring use of @JsonCreator 222 switch (p.currentTokenId()) { 223 case JsonTokenId.ID_STRING: 224 return finishBuild(ctxt, deserializeFromString(p, ctxt)); 225 case JsonTokenId.ID_NUMBER_INT: 226 return finishBuild(ctxt, deserializeFromNumber(p, ctxt)); 227 case JsonTokenId.ID_NUMBER_FLOAT: 228 return finishBuild(ctxt, deserializeFromDouble(p, ctxt)); 229 case JsonTokenId.ID_EMBEDDED_OBJECT: 230 return p.getEmbeddedObject(); 231 case JsonTokenId.ID_TRUE: 232 case JsonTokenId.ID_FALSE: 233 return finishBuild(ctxt, deserializeFromBoolean(p, ctxt)); 234 case JsonTokenId.ID_START_ARRAY: 235 // these only work if there's a (delegating) creator, or UNWRAP_SINGLE_ARRAY 236 // [databind#2608]: Do NOT call `finishBuild()` as method implements it 237 return _deserializeFromArray(p, ctxt); 238 case JsonTokenId.ID_FIELD_NAME: 239 case JsonTokenId.ID_END_OBJECT: 240 return finishBuild(ctxt, deserializeFromObject(p, ctxt)); 241 default: 242 } 243 return ctxt.handleUnexpectedToken(getValueType(ctxt), p); 244 } 245 246 /** 247 * Secondary deserialization method, called in cases where POJO 248 * instance is created as part of deserialization, potentially 249 * after collecting some or all of the properties to set. 250 */ 251 @Override deserialize(JsonParser p, DeserializationContext ctxt, Object value)252 public Object deserialize(JsonParser p, DeserializationContext ctxt, 253 Object value) throws IOException 254 { 255 // 26-Oct-2016, tatu: I cannot see any of making this actually 256 // work correctly, so let's indicate problem right away 257 JavaType valueType = _targetType; 258 // Did they try to give us builder? 259 Class<?> builderRawType = handledType(); 260 Class<?> instRawType = value.getClass(); 261 if (builderRawType.isAssignableFrom(instRawType)) { 262 return ctxt.reportBadDefinition(valueType, String.format( 263 "Deserialization of %s by passing existing Builder (%s) instance not supported", 264 valueType, builderRawType.getName())); 265 } 266 return ctxt.reportBadDefinition(valueType, String.format( 267 "Deserialization of %s by passing existing instance (of %s) not supported", 268 valueType, instRawType.getName())); 269 } 270 271 /* 272 /********************************************************** 273 /* Concrete deserialization methods 274 /********************************************************** 275 */ 276 277 /** 278 * Streamlined version that is only used when no "special" 279 * features are enabled. 280 */ vanillaDeserialize(JsonParser p, DeserializationContext ctxt, JsonToken t)281 private final Object vanillaDeserialize(JsonParser p, 282 DeserializationContext ctxt, JsonToken t) 283 throws IOException 284 { 285 Object bean = _valueInstantiator.createUsingDefault(ctxt); 286 for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) { 287 String propName = p.currentName(); 288 // Skip field name: 289 p.nextToken(); 290 SettableBeanProperty prop = _beanProperties.find(propName); 291 if (prop != null) { // normal case 292 try { 293 bean = prop.deserializeSetAndReturn(p, ctxt, bean); 294 } catch (Exception e) { 295 wrapAndThrow(e, bean, propName, ctxt); 296 } 297 } else { 298 handleUnknownVanilla(p, ctxt, bean, propName); 299 } 300 } 301 return bean; 302 } 303 304 /** 305 * General version used when handling needs more advanced 306 * features. 307 */ 308 @Override deserializeFromObject(JsonParser p, DeserializationContext ctxt)309 public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) 310 throws IOException 311 { 312 if (_nonStandardCreation) { 313 if (_unwrappedPropertyHandler != null) { 314 return deserializeWithUnwrapped(p, ctxt); 315 } 316 if (_externalTypeIdHandler != null) { 317 return deserializeWithExternalTypeId(p, ctxt); 318 } 319 return deserializeFromObjectUsingNonDefault(p, ctxt); 320 } 321 Object bean = _valueInstantiator.createUsingDefault(ctxt); 322 if (_injectables != null) { 323 injectValues(ctxt, bean); 324 } 325 if (_needViewProcesing) { 326 Class<?> view = ctxt.getActiveView(); 327 if (view != null) { 328 return deserializeWithView(p, ctxt, bean, view); 329 } 330 } 331 for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) { 332 String propName = p.currentName(); 333 // Skip field name: 334 p.nextToken(); 335 SettableBeanProperty prop = _beanProperties.find(propName); 336 if (prop != null) { // normal case 337 try { 338 bean = prop.deserializeSetAndReturn(p, ctxt, bean); 339 } catch (Exception e) { 340 wrapAndThrow(e, bean, propName, ctxt); 341 } 342 continue; 343 } 344 handleUnknownVanilla(p, ctxt, bean, propName); 345 } 346 return bean; 347 } 348 349 /** 350 * Method called to deserialize bean using "property-based creator": 351 * this means that a non-default constructor or factory method is 352 * called, and then possibly other setters. The trick is that 353 * values for creator method need to be buffered, first; and 354 * due to non-guaranteed ordering possibly some other properties 355 * as well. 356 * 357 * @return Builder instance constructed 358 */ 359 @Override 360 @SuppressWarnings("resource") _deserializeUsingPropertyBased(final JsonParser p, final DeserializationContext ctxt)361 protected Object _deserializeUsingPropertyBased(final JsonParser p, 362 final DeserializationContext ctxt) 363 throws IOException 364 { 365 final PropertyBasedCreator creator = _propertyBasedCreator; 366 PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); 367 final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null; 368 369 // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases 370 TokenBuffer unknown = null; 371 372 JsonToken t = p.currentToken(); 373 for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { 374 String propName = p.currentName(); 375 p.nextToken(); // to point to value 376 // creator property? 377 SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); 378 if (creatorProp != null) { 379 if ((activeView != null) && !creatorProp.visibleInView(activeView)) { 380 p.skipChildren(); 381 continue; 382 } 383 // Last creator property to set? 384 if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { 385 p.nextToken(); // to move to following FIELD_NAME/END_OBJECT 386 Object builder; 387 try { 388 builder = creator.build(ctxt, buffer); 389 } catch (Exception e) { 390 wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); 391 continue; // never gets here 392 } 393 // polymorphic? 394 if (builder.getClass() != _beanType.getRawClass()) { 395 return handlePolymorphic(p, ctxt, builder, unknown); 396 } 397 if (unknown != null) { // nope, just extra unknown stuff... 398 builder = handleUnknownProperties(ctxt, builder, unknown); 399 } 400 // or just clean? 401 return _deserialize(p, ctxt, builder); 402 } 403 continue; 404 } 405 // Object Id property? 406 if (buffer.readIdProperty(propName)) { 407 continue; 408 } 409 // regular property? needs buffering 410 SettableBeanProperty prop = _beanProperties.find(propName); 411 if (prop != null) { 412 buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); 413 continue; 414 } 415 // As per [JACKSON-313], things marked as ignorable should not be 416 // passed to any setter 417 if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) { 418 handleIgnoredProperty(p, ctxt, handledType(), propName); 419 continue; 420 } 421 // "any property"? 422 if (_anySetter != null) { 423 buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); 424 continue; 425 } 426 // Ok then, let's collect the whole field; name and value 427 if (unknown == null) { 428 unknown = new TokenBuffer(p, ctxt); 429 } 430 unknown.writeFieldName(propName); 431 unknown.copyCurrentStructure(p); 432 } 433 434 // We hit END_OBJECT, so: 435 Object builder; 436 try { 437 builder = creator.build(ctxt, buffer); 438 } catch (Exception e) { 439 builder = wrapInstantiationProblem(e, ctxt); 440 } 441 if (unknown != null) { 442 // polymorphic? 443 if (builder.getClass() != _beanType.getRawClass()) { 444 return handlePolymorphic(null, ctxt, builder, unknown); 445 } 446 // no, just some extra unknown properties 447 return handleUnknownProperties(ctxt, builder, unknown); 448 } 449 return builder; 450 } 451 452 @SuppressWarnings("resource") _deserialize(JsonParser p, DeserializationContext ctxt, Object builder)453 protected final Object _deserialize(JsonParser p, 454 DeserializationContext ctxt, Object builder) throws IOException 455 { 456 if (_injectables != null) { 457 injectValues(ctxt, builder); 458 } 459 if (_unwrappedPropertyHandler != null) { 460 if (p.hasToken(JsonToken.START_OBJECT)) { 461 p.nextToken(); 462 } 463 TokenBuffer tokens = new TokenBuffer(p, ctxt); 464 tokens.writeStartObject(); 465 return deserializeWithUnwrapped(p, ctxt, builder, tokens); 466 } 467 if (_externalTypeIdHandler != null) { 468 return deserializeWithExternalTypeId(p, ctxt, builder); 469 } 470 if (_needViewProcesing) { 471 Class<?> view = ctxt.getActiveView(); 472 if (view != null) { 473 return deserializeWithView(p, ctxt, builder, view); 474 } 475 } 476 JsonToken t = p.currentToken(); 477 // 23-Mar-2010, tatu: In some cases, we start with full JSON object too... 478 if (t == JsonToken.START_OBJECT) { 479 t = p.nextToken(); 480 } 481 for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { 482 String propName = p.currentName(); 483 // Skip field name: 484 p.nextToken(); 485 SettableBeanProperty prop = _beanProperties.find(propName); 486 487 if (prop != null) { // normal case 488 try { 489 builder = prop.deserializeSetAndReturn(p, ctxt, builder); 490 } catch (Exception e) { 491 wrapAndThrow(e, builder, propName, ctxt); 492 } 493 continue; 494 } 495 handleUnknownVanilla(p, ctxt, builder, propName); 496 } 497 return builder; 498 } 499 500 @Override // since 2.11, custom implementation _deserializeFromArray(JsonParser p, DeserializationContext ctxt)501 protected Object _deserializeFromArray(JsonParser p, DeserializationContext ctxt) throws IOException 502 { 503 // note: cannot call `_delegateDeserializer()` since order reversed here: 504 JsonDeserializer<Object> delegateDeser = _arrayDelegateDeserializer; 505 // fallback to non-array delegate 506 if ((delegateDeser != null) || ((delegateDeser = _delegateDeserializer) != null)) { 507 Object builder = _valueInstantiator.createUsingArrayDelegate(ctxt, 508 delegateDeser.deserialize(p, ctxt)); 509 if (_injectables != null) { 510 injectValues(ctxt, builder); 511 } 512 return finishBuild(ctxt, builder); 513 } 514 final CoercionAction act = _findCoercionFromEmptyArray(ctxt); 515 final boolean unwrap = ctxt.isEnabled(DeserializationFeature.UNWRAP_SINGLE_VALUE_ARRAYS); 516 517 if (unwrap || (act != CoercionAction.Fail)) { 518 JsonToken t = p.nextToken(); 519 if (t == JsonToken.END_ARRAY) { 520 switch (act) { 521 case AsEmpty: 522 return getEmptyValue(ctxt); 523 case AsNull: 524 case TryConvert: 525 return getNullValue(ctxt); 526 default: 527 } 528 return ctxt.handleUnexpectedToken(getValueType(ctxt), JsonToken.START_ARRAY, p, null); 529 } 530 if (unwrap) { 531 final Object value = deserialize(p, ctxt); 532 if (p.nextToken() != JsonToken.END_ARRAY) { 533 handleMissingEndArrayForSingle(p, ctxt); 534 } 535 return value; 536 } 537 } 538 return ctxt.handleUnexpectedToken(getValueType(ctxt), p); 539 } 540 541 /* 542 /********************************************************** 543 /* Deserializing when we have to consider an active View 544 /********************************************************** 545 */ 546 deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class<?> activeView)547 protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt, 548 Object bean, Class<?> activeView) 549 throws IOException 550 { 551 JsonToken t = p.currentToken(); 552 for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { 553 String propName = p.currentName(); 554 // Skip field name: 555 p.nextToken(); 556 SettableBeanProperty prop = _beanProperties.find(propName); 557 if (prop != null) { 558 if (!prop.visibleInView(activeView)) { 559 p.skipChildren(); 560 continue; 561 } 562 try { 563 bean = prop.deserializeSetAndReturn(p, ctxt, bean); 564 } catch (Exception e) { 565 wrapAndThrow(e, bean, propName, ctxt); 566 } 567 continue; 568 } 569 handleUnknownVanilla(p, ctxt, bean, propName); 570 } 571 return bean; 572 } 573 574 /* 575 /********************************************************** 576 /* Handling for cases where we have "unwrapped" values 577 /********************************************************** 578 */ 579 580 /** 581 * Method called when there are declared "unwrapped" properties 582 * which need special handling 583 */ 584 @SuppressWarnings("resource") deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt)585 protected Object deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt) 586 throws IOException 587 { 588 if (_delegateDeserializer != null) { 589 return _valueInstantiator.createUsingDelegate(ctxt, _delegateDeserializer.deserialize(p, ctxt)); 590 } 591 if (_propertyBasedCreator != null) { 592 return deserializeUsingPropertyBasedWithUnwrapped(p, ctxt); 593 } 594 TokenBuffer tokens = new TokenBuffer(p, ctxt); 595 tokens.writeStartObject(); 596 Object bean = _valueInstantiator.createUsingDefault(ctxt); 597 598 if (_injectables != null) { 599 injectValues(ctxt, bean); 600 } 601 602 final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null; 603 for (; p.currentToken() == JsonToken.FIELD_NAME; p.nextToken()) { 604 String propName = p.currentName(); 605 p.nextToken(); 606 SettableBeanProperty prop = _beanProperties.find(propName); 607 if (prop != null) { // normal case 608 if (activeView != null && !prop.visibleInView(activeView)) { 609 p.skipChildren(); 610 continue; 611 } 612 try { 613 bean = prop.deserializeSetAndReturn(p, ctxt, bean); 614 } catch (Exception e) { 615 wrapAndThrow(e, bean, propName, ctxt); 616 } 617 continue; 618 } 619 // ignorable things should be ignored 620 if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) { 621 handleIgnoredProperty(p, ctxt, bean, propName); 622 continue; 623 } 624 // but... others should be passed to unwrapped property deserializers 625 tokens.writeFieldName(propName); 626 tokens.copyCurrentStructure(p); 627 // how about any setter? We'll get copies but... 628 if (_anySetter != null) { 629 try { 630 _anySetter.deserializeAndSet(p, ctxt, bean, propName); 631 } catch (Exception e) { 632 wrapAndThrow(e, bean, propName, ctxt); 633 } 634 continue; 635 } 636 } 637 tokens.writeEndObject(); 638 return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, bean, tokens); 639 } 640 641 @SuppressWarnings("resource") deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, DeserializationContext ctxt)642 protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, 643 DeserializationContext ctxt) 644 throws IOException 645 { 646 final PropertyBasedCreator creator = _propertyBasedCreator; 647 PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); 648 649 TokenBuffer tokens = new TokenBuffer(p, ctxt); 650 tokens.writeStartObject(); 651 Object builder = null; 652 653 JsonToken t = p.currentToken(); 654 for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) { 655 String propName = p.currentName(); 656 p.nextToken(); // to point to value 657 // creator property? 658 SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); 659 if (creatorProp != null) { 660 // Last creator property to set? 661 if (buffer.assignParameter(creatorProp, creatorProp.deserialize(p, ctxt))) { 662 t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT 663 try { 664 builder = creator.build(ctxt, buffer); 665 } catch (Exception e) { 666 wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); 667 continue; // never gets here 668 } 669 if (builder.getClass() != _beanType.getRawClass()) { 670 return handlePolymorphic(p, ctxt, builder, tokens); 671 } 672 return deserializeWithUnwrapped(p, ctxt, builder, tokens); 673 } 674 continue; 675 } 676 // Object Id property? 677 if (buffer.readIdProperty(propName)) { 678 continue; 679 } 680 // regular property? needs buffering 681 SettableBeanProperty prop = _beanProperties.find(propName); 682 if (prop != null) { 683 buffer.bufferProperty(prop, prop.deserialize(p, ctxt)); 684 continue; 685 } 686 if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) { 687 handleIgnoredProperty(p, ctxt, handledType(), propName); 688 continue; 689 } 690 tokens.writeFieldName(propName); 691 tokens.copyCurrentStructure(p); 692 // "any property"? 693 if (_anySetter != null) { 694 buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(p, ctxt)); 695 } 696 } 697 tokens.writeEndObject(); 698 699 // We hit END_OBJECT, so: 700 if (builder == null) { 701 try { 702 builder = creator.build(ctxt, buffer); 703 } catch (Exception e) { 704 return wrapInstantiationProblem(e, ctxt); 705 } 706 } 707 return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens); 708 } 709 deserializeWithUnwrapped(JsonParser p, DeserializationContext ctxt, Object builder, TokenBuffer tokens)710 protected Object deserializeWithUnwrapped(JsonParser p, 711 DeserializationContext ctxt, Object builder, TokenBuffer tokens) 712 throws IOException 713 { 714 final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null; 715 for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { 716 String propName = p.currentName(); 717 SettableBeanProperty prop = _beanProperties.find(propName); 718 p.nextToken(); 719 if (prop != null) { // normal case 720 if (activeView != null && !prop.visibleInView(activeView)) { 721 p.skipChildren(); 722 continue; 723 } 724 try { 725 builder = prop.deserializeSetAndReturn(p, ctxt, builder); 726 } catch (Exception e) { 727 wrapAndThrow(e, builder, propName, ctxt); 728 } 729 continue; 730 } 731 if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) { 732 handleIgnoredProperty(p, ctxt, builder, propName); 733 continue; 734 } 735 // but... others should be passed to unwrapped property deserializers 736 tokens.writeFieldName(propName); 737 tokens.copyCurrentStructure(p); 738 // how about any setter? We'll get copies but... 739 if (_anySetter != null) { 740 _anySetter.deserializeAndSet(p, ctxt, builder, propName); 741 } 742 } 743 tokens.writeEndObject(); 744 return _unwrappedPropertyHandler.processUnwrapped(p, ctxt, builder, tokens); 745 } 746 747 /* 748 /********************************************************** 749 /* Handling for cases where we have property/-ies with 750 /* external type id 751 /********************************************************** 752 */ 753 deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)754 protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt) 755 throws IOException 756 { 757 if (_propertyBasedCreator != null) { 758 return deserializeUsingPropertyBasedWithExternalTypeId(p, ctxt); 759 } 760 return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt)); 761 } 762 deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean)763 protected Object deserializeWithExternalTypeId(JsonParser p, 764 DeserializationContext ctxt, Object bean) 765 throws IOException 766 { 767 final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null; 768 final ExternalTypeHandler ext = _externalTypeIdHandler.start(); 769 770 for (JsonToken t = p.currentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { 771 String propName = p.currentName(); 772 t = p.nextToken(); 773 SettableBeanProperty prop = _beanProperties.find(propName); 774 if (prop != null) { // normal case 775 // May have property AND be used as external type id: 776 if (t.isScalarValue()) { 777 ext.handleTypePropertyValue(p, ctxt, propName, bean); 778 } 779 if (activeView != null && !prop.visibleInView(activeView)) { 780 p.skipChildren(); 781 continue; 782 } 783 try { 784 bean = prop.deserializeSetAndReturn(p, ctxt, bean); 785 } catch (Exception e) { 786 wrapAndThrow(e, bean, propName, ctxt); 787 } 788 continue; 789 } 790 // ignorable things should be ignored 791 if (IgnorePropertiesUtil.shouldIgnore(propName, _ignorableProps, _includableProps)) { 792 handleIgnoredProperty(p, ctxt, bean, propName); 793 continue; 794 } 795 // but others are likely to be part of external type id thingy... 796 if (ext.handlePropertyValue(p, ctxt, propName, bean)) { 797 continue; 798 } 799 // if not, the usual fallback handling: 800 if (_anySetter != null) { 801 try { 802 _anySetter.deserializeAndSet(p, ctxt, bean, propName); 803 } catch (Exception e) { 804 wrapAndThrow(e, bean, propName, ctxt); 805 } 806 continue; 807 } else { 808 // Unknown: let's call handler method 809 handleUnknownProperty(p, ctxt, bean, propName); 810 } 811 } 812 // and when we get this far, let's try finalizing the deal: 813 return ext.complete(p, ctxt, bean); 814 } 815 deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, DeserializationContext ctxt)816 protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, 817 DeserializationContext ctxt) 818 throws IOException 819 { 820 // !!! 04-Mar-2012, TODO: Need to fix -- will not work as is... 821 JavaType t = _targetType; 822 return ctxt.reportBadDefinition(t, String.format( 823 "Deserialization (of %s) with Builder, External type id, @JsonCreator not yet implemented", 824 t)); 825 } 826 } 827