11
11
import com .fasterxml .jackson .core .JsonParser .NumberType ;
12
12
13
13
import com .fasterxml .jackson .databind .*;
14
+ import com .fasterxml .jackson .databind .cfg .ConfigOverride ;
14
15
import com .fasterxml .jackson .databind .deser .impl .*;
15
16
import com .fasterxml .jackson .databind .deser .std .StdDelegatingDeserializer ;
16
17
import com .fasterxml .jackson .databind .deser .std .StdDeserializer ;
@@ -695,12 +696,29 @@ protected void _replaceProperty(BeanPropertyMap props, SettableBeanProperty[] cr
695
696
696
697
@ SuppressWarnings ("unchecked" )
697
698
private JsonDeserializer <Object > _findDelegateDeserializer (DeserializationContext ctxt ,
698
- JavaType delegateType , AnnotatedWithParams delegateCreator ) throws JsonMappingException
699
+ JavaType delegateType , AnnotatedWithParams delegateCreator )
700
+ throws JsonMappingException
699
701
{
700
- // Need to create a temporary property to allow contextual deserializers:
701
- BeanProperty .Std property = new BeanProperty .Std (TEMP_PROPERTY_NAME ,
702
- delegateType , null , delegateCreator ,
703
- PropertyMetadata .STD_OPTIONAL );
702
+ // 27-Nov-2023, tatu: [databind#4200] Need to resolve PropertyMetadata.
703
+ // And all we have is the actual Creator method; but for annotations
704
+ // we actually need the one parameter -- if there is one
705
+ // (NOTE! This would not work for case of more than one parameter with
706
+ // delegation, others injected)
707
+ final BeanProperty property ;
708
+
709
+ if ((delegateCreator != null ) && (delegateCreator .getParameterCount () == 1 )) {
710
+ AnnotatedMember delegator = delegateCreator .getParameter (0 );
711
+ PropertyMetadata propMd = _getSetterInfo (ctxt , delegator , delegateType );
712
+ property = new BeanProperty .Std (TEMP_PROPERTY_NAME ,
713
+ delegateType , null , delegator , propMd );
714
+ } else {
715
+ // No creator indicated; or Zero, or more than 2 arguments (since we don't
716
+ // know which one is the "real" delegating parameter. Although could possibly
717
+ // figure it out if someone provides actual use case
718
+ property = new BeanProperty .Std (TEMP_PROPERTY_NAME ,
719
+ delegateType , null , delegateCreator ,
720
+ PropertyMetadata .STD_OPTIONAL );
721
+ }
704
722
TypeDeserializer td = delegateType .getTypeHandler ();
705
723
if (td == null ) {
706
724
td = ctxt .getConfig ().findTypeDeserializer (delegateType );
@@ -720,6 +738,62 @@ private JsonDeserializer<Object> _findDelegateDeserializer(DeserializationContex
720
738
return dd ;
721
739
}
722
740
741
+ /**
742
+ * Method essentially copied from {@code BasicDeserializerFactory},
743
+ * needed to find {@link PropertyMetadata} for Delegating Creator,
744
+ * for access to annotation-derived info.
745
+ *
746
+ * @since 2.16.1
747
+ */
748
+ protected PropertyMetadata _getSetterInfo (DeserializationContext ctxt ,
749
+ AnnotatedMember accessor , JavaType type )
750
+ {
751
+ final AnnotationIntrospector intr = ctxt .getAnnotationIntrospector ();
752
+ final DeserializationConfig config = ctxt .getConfig ();
753
+
754
+ PropertyMetadata metadata = PropertyMetadata .STD_OPTIONAL ;
755
+ boolean needMerge = true ;
756
+ Nulls valueNulls = null ;
757
+ Nulls contentNulls = null ;
758
+
759
+ // NOTE: compared to `POJOPropertyBuilder`, we only have access to creator
760
+ // parameter, not other accessors, so code bit simpler
761
+ // Ok, first: does property itself have something to say?
762
+ if (intr != null ) {
763
+ JsonSetter .Value setterInfo = intr .findSetterInfo (accessor );
764
+ if (setterInfo != null ) {
765
+ valueNulls = setterInfo .nonDefaultValueNulls ();
766
+ contentNulls = setterInfo .nonDefaultContentNulls ();
767
+ }
768
+ }
769
+ // If not, config override?
770
+ if (needMerge || (valueNulls == null ) || (contentNulls == null )) {
771
+ ConfigOverride co = config .getConfigOverride (type .getRawClass ());
772
+ JsonSetter .Value setterInfo = co .getSetterInfo ();
773
+ if (setterInfo != null ) {
774
+ if (valueNulls == null ) {
775
+ valueNulls = setterInfo .nonDefaultValueNulls ();
776
+ }
777
+ if (contentNulls == null ) {
778
+ contentNulls = setterInfo .nonDefaultContentNulls ();
779
+ }
780
+ }
781
+ }
782
+ if (needMerge || (valueNulls == null ) || (contentNulls == null )) {
783
+ JsonSetter .Value setterInfo = config .getDefaultSetterInfo ();
784
+ if (valueNulls == null ) {
785
+ valueNulls = setterInfo .nonDefaultValueNulls ();
786
+ }
787
+ if (contentNulls == null ) {
788
+ contentNulls = setterInfo .nonDefaultContentNulls ();
789
+ }
790
+ }
791
+ if ((valueNulls != null ) || (contentNulls != null )) {
792
+ metadata = metadata .withNulls (valueNulls , contentNulls );
793
+ }
794
+ return metadata ;
795
+ }
796
+
723
797
/**
724
798
* Helper method that can be used to see if specified property is annotated
725
799
* to indicate use of a converter for property value (in case of container types,
0 commit comments