@@ -498,7 +498,8 @@ protected void _addImplicitConstructorCreators(DeserializationContext ctxt,
498
498
// some single-arg factory methods (String, number) are auto-detected
499
499
if (argCount == 1 ) {
500
500
final BeanPropertyDefinition propDef = candidate .propertyDef (0 );
501
- final boolean useProps = preferPropsBased || _checkIfCreatorPropertyBased (intr , ctor , propDef );
501
+ final boolean useProps = preferPropsBased
502
+ || _checkIfCreatorPropertyBased (beanDesc , intr , ctor , propDef );
502
503
503
504
if (useProps ) {
504
505
SettableBeanProperty [] properties = new SettableBeanProperty [1 ];
@@ -705,7 +706,7 @@ protected void _addImplicitFactoryCreators(DeserializationContext ctxt,
705
706
continue ; // 2 and more args? Must be explicit, handled earlier
706
707
}
707
708
BeanPropertyDefinition argDef = candidate .propertyDef (0 );
708
- boolean useProps = _checkIfCreatorPropertyBased (intr , factory , argDef );
709
+ boolean useProps = _checkIfCreatorPropertyBased (beanDesc , intr , factory , argDef );
709
710
if (!useProps ) { // not property based but delegating
710
711
/*boolean added=*/ _handleSingleArgumentCreator (creators ,
711
712
factory , false , vchecker .isCreatorVisible (factory ));
@@ -972,12 +973,16 @@ protected void _addExplicitAnyCreator(DeserializationContext ctxt,
972
973
if (!useProps && (paramDef != null )) {
973
974
// One more thing: if implicit name matches property with a getter
974
975
// or field, we'll consider it property-based as well
975
-
976
- // 25-May-2018, tatu: as per [databind#2051], looks like we have to get
977
- // not implicit name, but name with possible strategy-based-rename
976
+
977
+ // 01-Dec-2022, tatu: [databind#3654] Consider `@JsonValue` to strongly
978
+ // hint at delegation-based
979
+ if (beanDesc .findJsonValueAccessor () == null ) {
980
+ // 25-May-2018, tatu: as per [databind#2051], looks like we have to get
981
+ // not implicit name, but name with possible strategy-based-rename
978
982
// paramName = candidate.findImplicitParamName(0);
979
- paramName = candidate .paramName (0 );
980
- useProps = (paramName != null ) && paramDef .couldSerialize ();
983
+ paramName = candidate .paramName (0 );
984
+ useProps = (paramName != null ) && paramDef .couldSerialize ();
985
+ }
981
986
}
982
987
}
983
988
}
@@ -1000,14 +1005,21 @@ protected void _addExplicitAnyCreator(DeserializationContext ctxt,
1000
1005
}
1001
1006
}
1002
1007
1003
- private boolean _checkIfCreatorPropertyBased (AnnotationIntrospector intr ,
1008
+ private boolean _checkIfCreatorPropertyBased (BeanDescription beanDesc ,
1009
+ AnnotationIntrospector intr ,
1004
1010
AnnotatedWithParams creator , BeanPropertyDefinition propDef )
1005
1011
{
1006
1012
// If explicit name, or inject id, property-based
1007
1013
if (((propDef != null ) && propDef .isExplicitlyNamed ())
1008
1014
|| (intr .findInjectableValue (creator .getParameter (0 )) != null )) {
1009
1015
return true ;
1010
1016
}
1017
+ // 01-Dec-2022, tatu: [databind#3654] Consider `@JsonValue` to strongly
1018
+ // hint at delegation-based
1019
+ if (beanDesc .findJsonValueAccessor () != null ) {
1020
+ return false ;
1021
+ }
1022
+
1011
1023
if (propDef != null ) {
1012
1024
// One more thing: if implicit name matches property with a getter
1013
1025
// or field, we'll consider it property-based as well
0 commit comments