Skip to content

Commit

Permalink
Fix #3654
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Dec 2, 2022
1 parent e5a972f commit c084b8a
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 8 deletions.
1 change: 1 addition & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Project: jackson-databind

2.15.0 (not yet released)

#3654: Infer `@JsonCreator(mode = Mode.DELEGATING)` from use of `@JsonValue`)
#3676: Allow use of `@JsonCreator(mode = Mode.PROPERTIES)` creator for POJOs
with"empty String" coercion
#3680: Timestamp in classes inside jar showing 02/01/1980
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,8 @@ protected void _addImplicitConstructorCreators(DeserializationContext ctxt,
// some single-arg factory methods (String, number) are auto-detected
if (argCount == 1) {
final BeanPropertyDefinition propDef = candidate.propertyDef(0);
final boolean useProps = preferPropsBased || _checkIfCreatorPropertyBased(intr, ctor, propDef);
final boolean useProps = preferPropsBased
|| _checkIfCreatorPropertyBased(beanDesc, intr, ctor, propDef);

if (useProps) {
SettableBeanProperty[] properties = new SettableBeanProperty[1];
Expand Down Expand Up @@ -705,7 +706,7 @@ protected void _addImplicitFactoryCreators(DeserializationContext ctxt,
continue; // 2 and more args? Must be explicit, handled earlier
}
BeanPropertyDefinition argDef = candidate.propertyDef(0);
boolean useProps = _checkIfCreatorPropertyBased(intr, factory, argDef);
boolean useProps = _checkIfCreatorPropertyBased(beanDesc, intr, factory, argDef);
if (!useProps) { // not property based but delegating
/*boolean added=*/ _handleSingleArgumentCreator(creators,
factory, false, vchecker.isCreatorVisible(factory));
Expand Down Expand Up @@ -972,12 +973,16 @@ protected void _addExplicitAnyCreator(DeserializationContext ctxt,
if (!useProps && (paramDef != null)) {
// One more thing: if implicit name matches property with a getter
// or field, we'll consider it property-based as well

// 25-May-2018, tatu: as per [databind#2051], looks like we have to get
// not implicit name, but name with possible strategy-based-rename

// 01-Dec-2022, tatu: [databind#3654] Consider `@JsonValue` to strongly
// hint at delegation-based
if (beanDesc.findJsonValueAccessor() == null) {
// 25-May-2018, tatu: as per [databind#2051], looks like we have to get
// not implicit name, but name with possible strategy-based-rename
// paramName = candidate.findImplicitParamName(0);
paramName = candidate.paramName(0);
useProps = (paramName != null) && paramDef.couldSerialize();
paramName = candidate.paramName(0);
useProps = (paramName != null) && paramDef.couldSerialize();
}
}
}
}
Expand All @@ -1000,14 +1005,21 @@ protected void _addExplicitAnyCreator(DeserializationContext ctxt,
}
}

private boolean _checkIfCreatorPropertyBased(AnnotationIntrospector intr,
private boolean _checkIfCreatorPropertyBased(BeanDescription beanDesc,
AnnotationIntrospector intr,
AnnotatedWithParams creator, BeanPropertyDefinition propDef)
{
// If explicit name, or inject id, property-based
if (((propDef != null) && propDef.isExplicitlyNamed())
|| (intr.findInjectableValue(creator.getParameter(0)) != null)) {
return true;
}
// 01-Dec-2022, tatu: [databind#3654] Consider `@JsonValue` to strongly
// hint at delegation-based
if (beanDesc.findJsonValueAccessor() != null) {
return false;
}

if (propDef != null) {
// One more thing: if implicit name matches property with a getter
// or field, we'll consider it property-based as well
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.fasterxml.jackson.databind.deser.creators;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
Expand Down Expand Up @@ -45,6 +47,21 @@ public Bean2932(/*@com.fasterxml.jackson.annotation.JsonProperty("paramName0")*/
}
}

// [databind#3654]: infer "DELEGATING" style from `@JsonValue`
static class XY3654 {
public int paramName0; // has to be public to misdirect

@JsonCreator
public XY3654(int paramName0) {
this.paramName0 = paramName0;
}

@JsonValue
public int serializedAs() {
return paramName0;
}
}

/*
/**********************************************************
/* Test methods
Expand Down Expand Up @@ -72,4 +89,15 @@ public void testJsonCreatorWithOtherAnnotations() throws Exception
assertEquals(1, bean._a);
assertEquals(2, bean._b);
}

// [databind#3654]
public void testDelegatingInferFromJsonValue() throws Exception
{
// First verify serialization via `@JsonValue`
assertEquals("123", MAPPER.writeValueAsString(new XY3654(123)));

// And then deser, should infer despite existence of "matching" property
XY3654 result = MAPPER.readValue("345", XY3654.class);
assertEquals(345, result.paramName0);
}
}

0 comments on commit c084b8a

Please sign in to comment.