Skip to content

Commit

Permalink
Merge branch '2.18' into 2.19
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Nov 27, 2024
2 parents e96794f + 4d970ed commit 53f727a
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 17 deletions.
4 changes: 4 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -1857,6 +1857,10 @@ Mike Minicki (@martel)
* Reported #4788: `EnumFeature.WRITE_ENUMS_TO_LOWERCASE` overrides `@JsonProperty` values
(2.18.2)

Jonathan Mesny (@jmesny)
* Reported #4810: Deserialization using `@JsonCreator` with renamed property failing (since 2.18)
(2.18.2)

Liam Feid (@fxshlein)
* Contributed #1467: Support `@JsonUnwrapped` with `@JsonCreator`
(2.19.0)
Expand Down
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ Project: jackson-databind
(reported by @bsa01)
(fix by Joo-Hyuk K)
#4807: Improve `FactoryBasedEnumDeserializer` to work better with XML module
#4810: Deserialization using `@JsonCreator` with renamed property failing (since 2.18)
(reported by Jonathan M)

2.18.1 (28-Oct-2024)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -912,11 +912,23 @@ private boolean _isExplicitlyAnnotatedCreatorPropsBased(PotentialCreator ctor,
if (ctor.paramCount() == 1) {
// One more possibility: implicit name that maps to implied
// property with at least one visible accessor
String implName = ctor.implicitNameSimple(0);
if (implName != null) {
POJOPropertyBuilder prop = props.get(implName);
if ((prop != null) && prop.anyVisible() && !prop.anyIgnorals()) {
return true;
PropertyName paramName = ctor.implicitName(0);
if (paramName != null) {
POJOPropertyBuilder prop = props.get(paramName.getSimpleName());
if (prop != null) {
if (prop.anyVisible() && !prop.anyIgnorals()) {
return true;
}
} else {
// 26-Nov-2024, tatu: [databind#4810] Implicit name not always
// enough; may need to link to explicit name override
for (POJOPropertyBuilder pb : props.values()) {
if (pb.anyVisible()
&& !pb.anyIgnorals()
&& pb.hasExplicitName(paramName)) {
return true;
}
}
}
}
// Second: injectable also suffices
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ public int compareTo(POJOPropertyBuilder other)
} else if (other._ctorParameters != null) {
return 1;
}
/* otherwise sort by external name (including sorting of
* ctor parameters)
*/
// otherwise sort by external name (including sorting of ctor parameters)
return getName().compareTo(other.getName());
}

Expand Down Expand Up @@ -1231,10 +1229,36 @@ public Set<PropertyName> findExplicitNames()
renamed = _findExplicitNames(_getters, renamed);
renamed = _findExplicitNames(_setters, renamed);
renamed = _findExplicitNames(_ctorParameters, renamed);
if (renamed == null) {
return Collections.emptySet();
return (renamed == null) ? Collections.emptySet() : renamed;
}

/**
* Method find out if this property has specified explicit name: this
* is generally needed for properties that have not yet been renamed
* (Creator-detection).
*
* @param name Name to check against
*
* @return True if this property has specified explicit name
*
* @since 2.18.2
*/
public boolean hasExplicitName(PropertyName name) {
return _hasExplicitName(_fields, name)
|| _hasExplicitName(_getters, name)
|| _hasExplicitName(_setters, name)
|| _hasExplicitName(_ctorParameters, name);
}

private boolean _hasExplicitName(Linked<? extends AnnotatedMember> node,
PropertyName nameToMatch)
{
for (; node != null; node = node.next) {
if (node.isNameExplicit && nameToMatch.equals(node.name)) {
return true;
}
}
return renamed;
return false;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.testutil.DatabindTestUtil;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;

public class CreatorWithRenamedParamTest
Expand Down Expand Up @@ -42,23 +44,58 @@ public String getKey2() {
}
}

private final ObjectMapper MAPPER = jsonMapperBuilder()
.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)
.annotationIntrospector(new ImplicitNameIntrospector())
.build();
// [databind#4810]
static class DataClass4810 {
private String x;

private DataClass4810(String x) {
this.x = x;
}

@JsonProperty("bar")
public String getFoo() {
return x;
}

// NOTE: mode-less, should be properly detected as properties-based
@JsonCreator
public static DataClass4810 create(@ImplicitName("bar") String bar) {
return new DataClass4810(bar);
}
}

// [databind#4545]
@Test
public void testCreatorWithRename4545() throws Exception
public void creatorWithRename4545() throws Exception
{
final ObjectMapper mapper4545 = jsonMapperBuilder()
.disable(MapperFeature.ALLOW_FINAL_FIELDS_AS_MUTATORS)
.annotationIntrospector(new ImplicitNameIntrospector())
.build();
String jsonPayload = a2q("{ 'key1': 'val1', 'key2': 'val2'}");

try {
MAPPER.readValue(jsonPayload, Payload4545.class);
mapper4545.readValue(jsonPayload, Payload4545.class);
fail("Should not pass");
} catch (UnrecognizedPropertyException e) {
verifyException(e, "Unrecognized");
verifyException(e, "key1");
}
}

// [databind#4810]
@Test
void shouldSupportPropertyRenaming4810() throws Exception {
ObjectMapper mapper = JsonMapper.builder()
.annotationIntrospector(new ImplicitNameIntrospector())
.build();

JsonNode serializationResult = mapper.valueToTree(DataClass4810.create("42"));

assertEquals(a2q("{'bar':'42'}"), serializationResult.toString());

DataClass4810 deserializationResult = mapper.treeToValue(serializationResult, DataClass4810.class);

assertEquals("42", deserializationResult.getFoo());
}
}

0 comments on commit 53f727a

Please sign in to comment.