Skip to content

Commit d662592

Browse files
committed
Fixed #2757
1 parent 5d1f645 commit d662592

File tree

6 files changed

+118
-64
lines changed

6 files changed

+118
-64
lines changed

release-notes/CREDITS-2.x

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,26 +1081,26 @@ Robert Diebels (RobertDiebels@github)
10811081
Joseph Koshakow (jkosh44@github)
10821082
* Contributed fix for #2515: `ObjectMapper.registerSubtypes(NamedType...)` doesn't allow registering
10831083
the same POJO for two different type ids
1084-
(2.11.0)
1084+
(2.11.0)
10851085
10861086
Haowei Wen (yushijinhun@github)
10871087
* Reported #2565: Java 8 `Optional` not working with `@JsonUnwrapped` on unwrappable type
1088-
(2.11.0)
1088+
(2.11.0)
10891089
10901090
Bartosz Baranowski (baranowb@github)
10911091
* Reported #2589: `DOMDeserializer`: setExpandEntityReferences(false) may not prevent
10921092
external entity expansion in all cases
1093-
(2.11.0)
1093+
(2.11.0)
10941094
10951095
Oleksii Khomchenko (gagoman@github)
10961096
* Reported, contributed fix for #2592: `ObjectMapper.setSerializationInclusion()` is
10971097
ignored for `JsonAnyGetter`
1098-
(2.11.0)
1098+
(2.11.0)
10991099
11001100
Oleksandr Poslavskyi (alevskyi@github)
11011101
* Contributed fix for #1983: Polymorphic deserialization should handle case-insensitive Type Id
11021102
property name if `MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES` is enabled
1103-
(2.11.0)
1103+
(2.11.0)
11041104
11051105
Simone D'Avico (simonedavico@github)
11061106
* Reported #2632: Failure to resolve generic type parameters on serialization
@@ -1125,3 +1125,7 @@ Johannes Kuhn (DasBrain@github)
11251125
deserializer properties
11261126
(2.11.1)
11271127
1128+
Frank Schmager (fschmager@github)
1129+
* Reported #2757: "Conflicting setter definitions for property" exception for `Map`
1130+
subtype during deserialization
1131+
(2.11.1)

release-notes/VERSION-2.x

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ Project: jackson-databind
1414
#2755: `StdSubtypeResolver` is not thread safe (possibly due to copy
1515
not being made with `ObjectMapper.copy()`)
1616
(reported by tjwilson90@github)
17+
#2757: "Conflicting setter definitions for property" exception for `Map`
18+
subtype during deserialization
19+
(reported by Frank S)
1720
#2759: Rearranging of props when property-based generator is in use leads
1821
to incorrect output
1922
(reported by Oleg C)

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,12 +224,15 @@ public AnnotatedMember getNonConstructorMutator() {
224224
* the highest precedence in current context (getter method when serializing,
225225
* if available, and so forth), if any.
226226
*<p>
227+
* Note: may throw {@link IllegalArgumentException} in case problems are found
228+
* trying to getter or setter info.
229+
*<p>
227230
* Note: abstract since 2.5
228231
*
229232
* @since 2.1
230233
*/
231234
public abstract AnnotatedMember getPrimaryMember();
232-
235+
233236
/*
234237
/**********************************************************
235238
/* More refined access to configuration features

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

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,16 +239,20 @@ public PropertyMetadata getMetadata() {
239239
* Helper method that contains logic for accessing and merging all setter
240240
* information that we needed, regarding things like possible merging
241241
* of property value, and handling of incoming nulls.
242+
* Only called for deserialization purposes.
242243
*/
243244
protected PropertyMetadata _getSetterInfo(PropertyMetadata metadata)
244245
{
245246
boolean needMerge = true;
246247
Nulls valueNulls = null;
247248
Nulls contentNulls = null;
248-
249+
249250
// Slightly confusing: first, annotations should be accessed via primary member
250-
// (mutator); but accessor is needed for actual merge operation. So:
251-
AnnotatedMember prim = getPrimaryMember();
251+
// (mutator); but accessor is needed for actual merge operation. So
252+
253+
// 20-Jun-2020, tatu: Unfortunately strict checks lead to [databind#2757]
254+
// so we will need to try to avoid them at this point
255+
AnnotatedMember prim = getPrimaryMemberUnchecked();
252256
AnnotatedMember acc = getAccessor();
253257

254258
if (prim != null) {
@@ -272,7 +276,10 @@ protected PropertyMetadata _getSetterInfo(PropertyMetadata metadata)
272276
// If not, config override?
273277
// 25-Oct-2016, tatu: Either this, or type of accessor...
274278
if (needMerge || (valueNulls == null) || (contentNulls == null)) {
275-
Class<?> rawType = getRawPrimaryType();
279+
// 20-Jun-2020, tatu: Related to [databind#2757], need to find type
280+
// but keeping mind that type for setters is trickier; and that
281+
// generic typing gets tricky as well.
282+
Class<?> rawType = _rawTypeOf(prim);
276283
ConfigOverride co = _config.getConfigOverride(rawType);
277284
JsonSetter.Value setterInfo = co.getSetterInfo();
278285
if (setterInfo != null) {
@@ -330,7 +337,6 @@ public JavaType getPrimaryType() {
330337
// 09-Feb-2017, tatu: Not sure if this or `null` but...
331338
return TypeFactory.unknownType();
332339
}
333-
return m.getType();
334340
}
335341
return m.getType();
336342
}
@@ -577,6 +583,45 @@ public AnnotatedMember getPrimaryMember() {
577583
return m;
578584
}
579585

586+
// Sometimes we need to actually by-pass failures related to conflicting
587+
// getters or setters (see [databind#2757] for specific example); if so,
588+
// this method is to be used instead of `getPrimaryMember()`
589+
// @since 2.11.1
590+
protected AnnotatedMember getPrimaryMemberUnchecked() {
591+
if (_forSerialization) { // Inlined `getAccessor()` logic:
592+
// Inlined `getGetter()`:
593+
if (_getters != null) {
594+
return _getters.value;
595+
}
596+
// Inlined `getField()`:
597+
if (_fields != null) {
598+
return _fields.value;
599+
}
600+
return null;
601+
}
602+
603+
// Otherwise, inlined `getMutator()` logic:
604+
605+
// Inlined `getConstructorParameter()`:
606+
if (_ctorParameters != null) {
607+
return _ctorParameters.value;
608+
}
609+
// Inlined `getSetter()`:
610+
if (_setters != null) {
611+
return _setters.value;
612+
}
613+
// Inlined `getField()`:
614+
if (_fields != null) {
615+
return _fields.value;
616+
}
617+
// but to support setterless-properties, also include part of
618+
// `getAccessor()` not yet covered, `getGetter()`:
619+
if (_getters != null) {
620+
return _getters.value;
621+
}
622+
return null;
623+
}
624+
580625
protected int _getterPriority(AnnotatedMethod m)
581626
{
582627
final String name = m.getName();
@@ -1220,6 +1265,26 @@ protected <T> T fromMemberAnnotationsExcept(WithMember<T> func, T defaultValue)
12201265
return null;
12211266
}
12221267

1268+
// Helper method needed to work around oddity in type access for
1269+
// `AnnotatedMethod`.
1270+
//
1271+
// @since 2.11.1
1272+
protected Class<?> _rawTypeOf(AnnotatedMember m) {
1273+
// AnnotatedMethod always returns return type, but for setters we
1274+
// actually need argument type
1275+
if (m instanceof AnnotatedMethod) {
1276+
AnnotatedMethod meh = (AnnotatedMethod) m;
1277+
if (meh.getParameterCount() > 0) {
1278+
// note: get raw type FROM full type since only that resolves
1279+
// generic types
1280+
return meh.getParameterType(0).getRawClass();
1281+
}
1282+
}
1283+
// same as above, must get fully resolved type to handled generic typing
1284+
// of fields etc.
1285+
return m.getType().getRawClass();
1286+
}
1287+
12231288
/*
12241289
/**********************************************************
12251290
/* Helper classes
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.fasterxml.jackson.databind.deser.jdk;
2+
3+
import java.util.*;
4+
5+
import com.fasterxml.jackson.databind.*;
6+
7+
@SuppressWarnings("serial")
8+
public class MapDeser2757Test extends BaseMapTest
9+
{
10+
static class MyMap extends LinkedHashMap<String, String> {
11+
public MyMap() { }
12+
13+
public void setValue(StringWrapper w) { }
14+
public void setValue(IntWrapper w) { }
15+
16+
public long getValue() { return 0L; }
17+
}
18+
19+
// [databind#2757]: should allow deserialization as Map despite conflicting setters
20+
public void testCanDeserializeMap() throws Exception
21+
{
22+
final ObjectMapper mapper = jsonMapperBuilder()
23+
.build();
24+
25+
MyMap input = new MyMap();
26+
input.put("a", "b");
27+
final String json = mapper.writeValueAsString(input);
28+
MyMap x = mapper.readValue(json, MyMap.class);
29+
assertEquals(1, x.size());
30+
assertEquals("b", input.get("a"));
31+
}
32+
}

src/test/java/com/fasterxml/jackson/failing/ObjectMapper2757Test.java

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)