Skip to content

Commit

Permalink
Fixed #2757
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Jun 21, 2020
1 parent 5d1f645 commit d662592
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 64 deletions.
14 changes: 9 additions & 5 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -1081,26 +1081,26 @@ Robert Diebels (RobertDiebels@github)
Joseph Koshakow (jkosh44@github)
* Contributed fix for #2515: `ObjectMapper.registerSubtypes(NamedType...)` doesn't allow registering
the same POJO for two different type ids
(2.11.0)
(2.11.0)
Haowei Wen (yushijinhun@github)
* Reported #2565: Java 8 `Optional` not working with `@JsonUnwrapped` on unwrappable type
(2.11.0)
(2.11.0)
Bartosz Baranowski (baranowb@github)
* Reported #2589: `DOMDeserializer`: setExpandEntityReferences(false) may not prevent
external entity expansion in all cases
(2.11.0)
(2.11.0)
Oleksii Khomchenko (gagoman@github)
* Reported, contributed fix for #2592: `ObjectMapper.setSerializationInclusion()` is
ignored for `JsonAnyGetter`
(2.11.0)
(2.11.0)
Oleksandr Poslavskyi (alevskyi@github)
* Contributed fix for #1983: Polymorphic deserialization should handle case-insensitive Type Id
property name if `MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES` is enabled
(2.11.0)
(2.11.0)
Simone D'Avico (simonedavico@github)
* Reported #2632: Failure to resolve generic type parameters on serialization
Expand All @@ -1125,3 +1125,7 @@ Johannes Kuhn (DasBrain@github)
deserializer properties
(2.11.1)
Frank Schmager (fschmager@github)
* Reported #2757: "Conflicting setter definitions for property" exception for `Map`
subtype during deserialization
(2.11.1)
3 changes: 3 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Project: jackson-databind
#2755: `StdSubtypeResolver` is not thread safe (possibly due to copy
not being made with `ObjectMapper.copy()`)
(reported by tjwilson90@github)
#2757: "Conflicting setter definitions for property" exception for `Map`
subtype during deserialization
(reported by Frank S)
#2759: Rearranging of props when property-based generator is in use leads
to incorrect output
(reported by Oleg C)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,12 +224,15 @@ public AnnotatedMember getNonConstructorMutator() {
* the highest precedence in current context (getter method when serializing,
* if available, and so forth), if any.
*<p>
* Note: may throw {@link IllegalArgumentException} in case problems are found
* trying to getter or setter info.
*<p>
* Note: abstract since 2.5
*
* @since 2.1
*/
public abstract AnnotatedMember getPrimaryMember();

/*
/**********************************************************
/* More refined access to configuration features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,16 +239,20 @@ public PropertyMetadata getMetadata() {
* Helper method that contains logic for accessing and merging all setter
* information that we needed, regarding things like possible merging
* of property value, and handling of incoming nulls.
* Only called for deserialization purposes.
*/
protected PropertyMetadata _getSetterInfo(PropertyMetadata metadata)
{
boolean needMerge = true;
Nulls valueNulls = null;
Nulls contentNulls = null;

// Slightly confusing: first, annotations should be accessed via primary member
// (mutator); but accessor is needed for actual merge operation. So:
AnnotatedMember prim = getPrimaryMember();
// (mutator); but accessor is needed for actual merge operation. So

// 20-Jun-2020, tatu: Unfortunately strict checks lead to [databind#2757]
// so we will need to try to avoid them at this point
AnnotatedMember prim = getPrimaryMemberUnchecked();
AnnotatedMember acc = getAccessor();

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

// Sometimes we need to actually by-pass failures related to conflicting
// getters or setters (see [databind#2757] for specific example); if so,
// this method is to be used instead of `getPrimaryMember()`
// @since 2.11.1
protected AnnotatedMember getPrimaryMemberUnchecked() {
if (_forSerialization) { // Inlined `getAccessor()` logic:
// Inlined `getGetter()`:
if (_getters != null) {
return _getters.value;
}
// Inlined `getField()`:
if (_fields != null) {
return _fields.value;
}
return null;
}

// Otherwise, inlined `getMutator()` logic:

// Inlined `getConstructorParameter()`:
if (_ctorParameters != null) {
return _ctorParameters.value;
}
// Inlined `getSetter()`:
if (_setters != null) {
return _setters.value;
}
// Inlined `getField()`:
if (_fields != null) {
return _fields.value;
}
// but to support setterless-properties, also include part of
// `getAccessor()` not yet covered, `getGetter()`:
if (_getters != null) {
return _getters.value;
}
return null;
}

protected int _getterPriority(AnnotatedMethod m)
{
final String name = m.getName();
Expand Down Expand Up @@ -1220,6 +1265,26 @@ protected <T> T fromMemberAnnotationsExcept(WithMember<T> func, T defaultValue)
return null;
}

// Helper method needed to work around oddity in type access for
// `AnnotatedMethod`.
//
// @since 2.11.1
protected Class<?> _rawTypeOf(AnnotatedMember m) {
// AnnotatedMethod always returns return type, but for setters we
// actually need argument type
if (m instanceof AnnotatedMethod) {
AnnotatedMethod meh = (AnnotatedMethod) m;
if (meh.getParameterCount() > 0) {
// note: get raw type FROM full type since only that resolves
// generic types
return meh.getParameterType(0).getRawClass();
}
}
// same as above, must get fully resolved type to handled generic typing
// of fields etc.
return m.getType().getRawClass();
}

/*
/**********************************************************
/* Helper classes
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.fasterxml.jackson.databind.deser.jdk;

import java.util.*;

import com.fasterxml.jackson.databind.*;

@SuppressWarnings("serial")
public class MapDeser2757Test extends BaseMapTest
{
static class MyMap extends LinkedHashMap<String, String> {
public MyMap() { }

public void setValue(StringWrapper w) { }
public void setValue(IntWrapper w) { }

public long getValue() { return 0L; }
}

// [databind#2757]: should allow deserialization as Map despite conflicting setters
public void testCanDeserializeMap() throws Exception
{
final ObjectMapper mapper = jsonMapperBuilder()
.build();

MyMap input = new MyMap();
input.put("a", "b");
final String json = mapper.writeValueAsString(input);
MyMap x = mapper.readValue(json, MyMap.class);
assertEquals(1, x.size());
assertEquals("b", input.get("a"));
}
}

This file was deleted.

0 comments on commit d662592

Please sign in to comment.