Skip to content

Commit 05ab176

Browse files
committed
Fix #2543: Skip delegating creator arguments when collecting properties
1 parent 6493f5f commit 05ab176

File tree

2 files changed

+70
-1
lines changed

2 files changed

+70
-1
lines changed

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,10 @@ private void _addCreatorParam(Map<String, POJOPropertyBuilder> props,
760760
// ...or is a Records canonical constructor
761761
boolean isCanonicalConstructor = recordComponentName != null;
762762

763-
if ((creatorMode == null || creatorMode == JsonCreator.Mode.DISABLED) && !isCanonicalConstructor) {
763+
if ((creatorMode == null
764+
|| creatorMode == JsonCreator.Mode.DISABLED
765+
|| creatorMode == JsonCreator.Mode.DELEGATING)
766+
&& !isCanonicalConstructor) {
764767
return;
765768
}
766769
pn = PropertyName.construct(impl);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.fasterxml.jackson.databind.deser.creators;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
import com.fasterxml.jackson.databind.introspect.*;
7+
import org.junit.Test;
8+
9+
import static com.fasterxml.jackson.annotation.JsonCreator.Mode.DELEGATING;
10+
import static com.fasterxml.jackson.annotation.JsonCreator.Mode.PROPERTIES;
11+
import static com.fasterxml.jackson.databind.testutil.DatabindTestUtil.a2q;
12+
import static java.util.Objects.requireNonNull;
13+
import static org.assertj.core.api.Assertions.assertThatNoException;
14+
15+
public class DelegatingCreatorImplicitNames2543Test {
16+
static class Data {
17+
18+
final String part1;
19+
final String part2;
20+
21+
// this creator is considered a source of settable bean properties,
22+
// used during deserialization
23+
@JsonCreator(mode = PROPERTIES)
24+
public Data(@JsonProperty("part1") String part1,
25+
@JsonProperty("part2") String part2) {
26+
this.part1 = part1;
27+
this.part2 = part2;
28+
}
29+
30+
// no properties should be collected from this creator,
31+
// even though it has an argument with an implicit name
32+
@JsonCreator(mode = DELEGATING)
33+
public static Data fromFullData(String fullData) {
34+
String[] parts = fullData.split("\\s+", 2);
35+
return new Data(parts[0], parts[1]);
36+
}
37+
}
38+
39+
private static class DelegatingCreatorNamedArgumentIntrospector
40+
extends JacksonAnnotationIntrospector {
41+
public String findImplicitPropertyName(AnnotatedMember member) {
42+
if (member instanceof AnnotatedParameter p) {
43+
if (p.getOwner() instanceof AnnotatedMethod m) {
44+
if (requireNonNull(m.getAnnotation(JsonCreator.class)).mode() == DELEGATING)
45+
return "fullData";
46+
}
47+
}
48+
return super.findImplicitPropertyName(member);
49+
}
50+
}
51+
52+
private static final ObjectMapper MAPPER = new ObjectMapper()
53+
.setAnnotationIntrospector(new DelegatingCreatorNamedArgumentIntrospector());
54+
55+
@Test
56+
public void testDeserialization() {
57+
assertThatNoException()
58+
.isThrownBy(() -> MAPPER.readValue(a2q("{'part1':'a','part2':'b'}"), Data.class));
59+
}
60+
61+
@Test
62+
public void testDelegatingDeserialization() {
63+
assertThatNoException()
64+
.isThrownBy(() -> MAPPER.readValue(a2q("'a b'"), Data.class));
65+
}
66+
}

0 commit comments

Comments
 (0)