@@ -356,7 +356,6 @@ public BeanDeserializerBase(BeanDeserializerBase src, ObjectIdReader oir)
356
356
public BeanDeserializerBase (BeanDeserializerBase src , Set <String > ignorableProps )
357
357
{
358
358
super (src ._beanType );
359
-
360
359
_classAnnotations = src ._classAnnotations ;
361
360
_beanType = src ._beanType ;
362
361
@@ -461,55 +460,35 @@ public void resolve(DeserializationContext ctxt)
461
460
462
461
if (_valueInstantiator .canCreateFromObjectWith ()) {
463
462
creatorProps = _valueInstantiator .getFromObjectArguments (ctxt .getConfig ());
464
-
465
- // 21-Jun-2015, tatu: This resolution was duplicated later on and seems like
466
- // it really should be only done at a later point. So commented out in 2.8.
467
- // However, just in case there was a reason for it, leaving commented out
468
- // here instead of immediately removing.
469
-
470
- /*
471
- // also: need to try to resolve 'external' type ids...
472
- for (SettableBeanProperty prop : creatorProps) {
473
- if (prop.hasValueTypeDeserializer()) {
474
- TypeDeserializer typeDeser = prop.getValueTypeDeserializer();
475
- if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) {
476
- if (extTypes == null) {
477
- extTypes = new ExternalTypeHandler.Builder();
478
- }
479
- extTypes.addExternal(prop, typeDeser);
480
- }
481
- }
482
- }
483
- */
484
463
} else {
485
464
creatorProps = null ;
486
465
}
487
-
488
466
UnwrappedPropertyHandler unwrapped = null ;
489
467
490
- for (SettableBeanProperty origProp : _beanProperties ) {
491
- SettableBeanProperty prop = origProp ;
468
+ // 24-Mar-2017, tatu: Looks like we may have to iterate over
469
+ // properties twice, to handle potential issues with recursive
470
+ // types (see [databind#1575] f.ex).
492
471
493
- // May already have deserializer from annotations, if so, skip:
472
+ // First loop: find deserializer if not yet known, but do not yet
473
+ // contextualize (since that can lead to problems with self-references)
474
+ for (SettableBeanProperty prop : _beanProperties ) {
494
475
if (!prop .hasValueDeserializer ()) {
495
476
// [databind#125]: allow use of converters
496
477
JsonDeserializer <?> deser = findConvertingDeserializer (ctxt , prop );
497
478
if (deser == null ) {
498
- deser = findDeserializer (ctxt , prop .getType (), prop );
499
- }
500
- prop = prop .withValueDeserializer (deser );
501
- } else { // may need contextual version
502
- JsonDeserializer <Object > deser = prop .getValueDeserializer ();
503
- /* Important! This is the only place where actually handle "primary"
504
- * property deserializers -- call is different from other places.
505
- */
506
- JsonDeserializer <?> cd = ctxt .handlePrimaryContextualization (deser , prop ,
507
- prop .getType ());
508
- if (cd != deser ) {
509
- prop = prop .withValueDeserializer (cd );
479
+ deser = ctxt .findNonContextualValueDeserializer (prop .getType ());
510
480
}
481
+ SettableBeanProperty newProp = prop .withValueDeserializer (deser );
482
+ _replaceProperty (_beanProperties , creatorProps , prop , newProp );
511
483
}
484
+ }
512
485
486
+ // Second loop: contextualize, find other pieces
487
+ for (SettableBeanProperty origProp : _beanProperties ) {
488
+ SettableBeanProperty prop = origProp ;
489
+ JsonDeserializer <?> deser = prop .getValueDeserializer ();
490
+ deser = ctxt .handlePrimaryContextualization (deser , prop , prop .getType ());
491
+ prop = prop .withValueDeserializer (deser );
513
492
// Need to link managed references with matching back references
514
493
prop = _resolveManagedReferenceProperty (ctxt , prop );
515
494
@@ -525,36 +504,18 @@ public void resolve(DeserializationContext ctxt)
525
504
unwrapped = new UnwrappedPropertyHandler ();
526
505
}
527
506
unwrapped .addProperty (prop );
528
- /* 12-Dec-2014, tatu: As per [databind#647], we will have problems if
529
- * the original property is left in place. So let's remove it now.
530
- */
507
+ // 12-Dec-2014, tatu: As per [databind#647], we will have problems if
508
+ // the original property is left in place. So let's remove it now.
509
+ // 25-Mar-2017, tatu: Wonder if this could be problematic wrt creators?
531
510
_beanProperties .remove (prop );
532
511
continue ;
533
512
}
534
513
// non-static inner classes too:
535
514
prop = _resolveInnerClassValuedProperty (ctxt , prop );
536
515
if (prop != origProp ) {
537
- _beanProperties .replace (prop );
538
- // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
539
- if (creatorProps != null ) {
540
- // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
541
- // fully count on this? May need to revisit in future; seems to hold for now.
542
- for (int i = 0 , len = creatorProps .length ; i < len ; ++i ) {
543
- if (creatorProps [i ] == origProp ) {
544
- creatorProps [i ] = prop ;
545
- break ;
546
- }
547
- // ... as per above, it is possible we'd need to add this as fallback
548
- // if (but only if) identity check fails?
549
- /*
550
- if (creatorProps[i].getName().equals(prop.getName())) {
551
- creatorProps[i] = prop;
552
- break;
553
- }
554
- */
555
- }
556
- }
516
+ _replaceProperty (_beanProperties , creatorProps , origProp , prop );
557
517
}
518
+
558
519
// one more thing: if this property uses "external property" type inclusion,
559
520
// it needs different handling altogether
560
521
if (prop .hasValueTypeDeserializer ()) {
@@ -616,11 +577,38 @@ public void resolve(DeserializationContext ctxt)
616
577
if (unwrapped != null ) { // we consider this non-standard, to offline handling
617
578
_nonStandardCreation = true ;
618
579
}
619
-
620
580
// may need to disable vanilla processing, if unwrapped handling was enabled...
621
581
_vanillaProcessing = _vanillaProcessing && !_nonStandardCreation ;
622
582
}
623
583
584
+ /**
585
+ * @since 2.8.8
586
+ */
587
+ protected void _replaceProperty (BeanPropertyMap props , SettableBeanProperty [] creatorProps ,
588
+ SettableBeanProperty origProp , SettableBeanProperty newProp )
589
+ {
590
+ props .replace (newProp );
591
+ // [databind#795]: Make sure PropertyBasedCreator's properties stay in sync
592
+ if (creatorProps != null ) {
593
+ // 18-May-2015, tatu: _Should_ start with consistent set. But can we really
594
+ // fully count on this? May need to revisit in future; seems to hold for now.
595
+ for (int i = 0 , len = creatorProps .length ; i < len ; ++i ) {
596
+ if (creatorProps [i ] == origProp ) {
597
+ creatorProps [i ] = newProp ;
598
+ return ;
599
+ }
600
+ }
601
+ // ... as per above, it is possible we'd need to add this as fallback
602
+ // if (but only if) identity check fails?
603
+ /*
604
+ if (creatorProps[i].getName().equals(prop.getName())) {
605
+ creatorProps[i] = prop;
606
+ break;
607
+ }
608
+ */
609
+ }
610
+ }
611
+
624
612
private JsonDeserializer <Object > _findDelegateDeserializer (DeserializationContext ctxt , JavaType delegateType ,
625
613
AnnotatedWithParams delegateCreator ) throws JsonMappingException {
626
614
// Need to create a temporary property to allow contextual deserializers:
@@ -645,6 +633,9 @@ private JsonDeserializer<Object> _findDelegateDeserializer(DeserializationContex
645
633
* Helper method that can be used to see if specified property is annotated
646
634
* to indicate use of a converter for property value (in case of container types,
647
635
* it is container type itself, not key or content type).
636
+ *<p>
637
+ * NOTE: returned deserializer is NOT yet contextualized, caller needs to take
638
+ * care to do that.
648
639
*
649
640
* @since 2.2
650
641
*/
@@ -658,8 +649,10 @@ protected JsonDeserializer<Object> findConvertingDeserializer(DeserializationCon
658
649
if (convDef != null ) {
659
650
Converter <Object ,Object > conv = ctxt .converterInstance (prop .getMember (), convDef );
660
651
JavaType delegateType = conv .getInputType (ctxt .getTypeFactory ());
661
- JsonDeserializer <?> ser = ctxt .findContextualValueDeserializer (delegateType , prop );
662
- return new StdDelegatingDeserializer <Object >(conv , delegateType , ser );
652
+ // 25-Mar-2017, tatu: should not yet contextualize
653
+ // JsonDeserializer<?> deser = ctxt.findContextualValueDeserializer(delegateType, prop);
654
+ JsonDeserializer <?> deser = ctxt .findNonContextualValueDeserializer (delegateType );
655
+ return new StdDelegatingDeserializer <Object >(conv , delegateType , deser );
663
656
}
664
657
}
665
658
return null ;
@@ -677,7 +670,7 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
677
670
BeanProperty property ) throws JsonMappingException
678
671
{
679
672
ObjectIdReader oir = _objectIdReader ;
680
-
673
+
681
674
// First: may have an override for Object Id:
682
675
final AnnotationIntrospector intr = ctxt .getAnnotationIntrospector ();
683
676
final AnnotatedMember accessor = (property == null || intr == null )
0 commit comments