Skip to content

Commit

Permalink
Merge branch '2.4' into 2.5 (plus related #735 follow-up regards to 2…
Browse files Browse the repository at this point in the history
….5.x additions)

Conflicts:
	release-notes/VERSION
	src/test/java/com/fasterxml/jackson/databind/deser/TestCustomDeserializers.java
  • Loading branch information
cowtowncoder committed Mar 26, 2015
2 parents 436c309 + 1d57c20 commit 05db853
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 15 deletions.
8 changes: 6 additions & 2 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,15 @@ Project: jackson-databind
- Added new overload for `JsonSerializer.isEmpty()`, to eventually solve #588
- Improve error messaging (related to [jaxb-annotations#38]) to include known subtype ids.

2.4.6 (not yet released)
2.4.5.1 (26-Mar-2015)

#706: Add support for @JsonUnwrapper via JSON Schema module
Special one-off "micro patch" for:

#706: Add support for `@JsonUnwrapped` via JSON Schema module
#707: Error in getting string representation of an ObjectNode with a float number value
(reported by @navidqar)
#735: @JsonDeserialize on Map with contentUsing custom deserializer overwrites default behavior
(reported by blackfyre512@github) (regression due to #604)

2.4.5 (13-Jan-2015)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ public class CollectionDeserializer
protected final TypeDeserializer _valueTypeDeserializer;

// // Instance construction settings:

protected final ValueInstantiator _valueInstantiator;

/**
* Deserializer that is used iff delegate-based creator is
* to be used for deserializing from JSON Object.
Expand Down Expand Up @@ -121,7 +121,11 @@ protected CollectionDeserializer withResolved(JsonDeserializer<?> dd,
// Important: do NOT cache if polymorphic values
@Override // since 2.5
public boolean isCachable() {
return (_valueTypeDeserializer == null);
// 26-Mar-2015, tatu: As per [databind#735], need to be careful
return (_valueDeserializer == null)
&& (_valueTypeDeserializer == null)
&& (_delegateDeserializer == null)
;
}

/*
Expand Down Expand Up @@ -152,6 +156,7 @@ public CollectionDeserializer createContextual(DeserializationContext ctxt,
}
// also, often value deserializer is resolved here:
JsonDeserializer<?> valueDeser = _valueDeserializer;

// #125: May have a content converter
valueDeser = findConvertingContentDeserializer(ctxt, property, valueDeser);
final JavaType vt = _collectionType.getContentType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanPro
@Override
public boolean isCachable() {
// Important: do NOT cache if polymorphic values
return (_valueTypeDeserializer == null);
return (_valueDeserializer == null)
&& (_keyDeserializer == null)
&& (_valueTypeDeserializer == null);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ public EnumSetDeserializer withDeserializer(JsonDeserializer<?> deser) {
* let's cache instances by default.
*/
@Override
public boolean isCachable() { return true; }
public boolean isCachable() {
// One caveat: content deserializer should prevent caching
if (_enumType.getValueHandler() != null) {
return false;
}
return true;
}

@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,13 @@ public JsonDeserializer<Object> getContentDeserializer() {
*/
@Override
public boolean isCachable() {
return (_valueTypeDeserializer == null) && (_ignorableProperties == null);
/* As per [databind#735], existence of value or key deserializer (only passed
* if annotated to use non-standard one) should also prevent caching.
*/
return (_valueDeserializer == null)
&& (_keyDeserializer == null)
&& (_valueTypeDeserializer == null)
&& (_ignorableProperties == null);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,

@Override // since 2.5
public boolean isCachable() {
// Important: do NOT cache if polymorphic values
return (_elementTypeDeserializer == null);
// Important: do NOT cache if polymorphic values, or ones with custom deserializer
return (_elementDeserializer == null) && (_elementTypeDeserializer == null);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ protected StringCollectionDeserializer withResolved(JsonDeserializer<?> delegate

@Override // since 2.5
public boolean isCachable() {
return true;
// 26-Mar-2015, tatu: Important: prevent caching if custom deserializers are involved
return (_valueDeserializer == null) && (_delegateDeserializer == null);
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,13 @@ protected JsonDeserializer<?> _withResolved(JsonDeserializer<?> mapDeser,
* since it's not uncommon to "read anything"
*/
@Override
public boolean isCachable() { return true; }
public boolean isCachable() {
/* 26-Mar-2015, tatu: With respect to [databind#735], there are concerns over
* cachability. It seems like we SHOULD be safe here; but just in case there
* are problems with false sharing, this may need to be revisited.
*/
return true;
}

@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,22 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt, BeanPro
}
return this;
}

}

// For [databind#735]
public static class TestMapBean735 {

@JsonDeserialize(contentUsing = CustomDeserializer735.class)
public Map<String, Integer> map1;

public Map<String, Integer> map2;
}

public static class TestListBean735 {
public List<Integer> list1;

@JsonDeserialize(contentUsing = CustomDeserializer735.class)
public List<Integer> list100;
}

// for [databind#631]
Expand All @@ -235,7 +250,18 @@ static class Issue631Bean
@JsonDeserialize(using=ParentClassDeserializer.class)
public Object prop;
}


public static class CustomDeserializer735 extends StdDeserializer<Integer> {
public CustomDeserializer735() {
super(Integer.class);
}

@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
return 100 * p.getValueAsInt();
}
}

static class ParentClassDeserializer
extends StdScalarDeserializer<Object>
{
Expand All @@ -249,7 +275,7 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt)
Object parent = p.getCurrentValue();
String desc = (parent == null) ? "NULL" : parent.getClass().getSimpleName();
return "prop/"+ desc;
}
}
}

/*
Expand Down Expand Up @@ -382,4 +408,21 @@ public void testCurrentValueAccess() throws Exception
assertNotNull(bean);
assertEquals("prop/Issue631Bean", bean.prop);
}

// [databind#735]: erroneous application of custom deserializer
public void testCustomMapValueDeser735() throws Exception {
String json = "{\"map1\":{\"a\":1},\"map2\":{\"a\":1}}";
TestMapBean735 bean = MAPPER.readValue(json, TestMapBean735.class);

assertEquals(100, bean.map1.get("a").intValue());
assertEquals(1, bean.map2.get("a").intValue());
}

public void testCustomListValueDeser735() throws Exception {
String json = "{\"list1\":[1],\"list100\":[1]}";
TestListBean735 bean = MAPPER.readValue(json, TestListBean735.class);

assertEquals(1, bean.list1.get(0).intValue());
assertEquals(100, bean.list100.get(0).intValue());
}
}

0 comments on commit 05db853

Please sign in to comment.