aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatu Saloranta <tatu.saloranta@iki.fi>2019-11-26 15:29:17 -0800
committerTatu Saloranta <tatu.saloranta@iki.fi>2019-11-26 15:29:17 -0800
commitedcec24754991bcb08827b95f83bd1f37b5437c7 (patch)
tree6b8a4a6d2eb628c3c772ad0dea26d2050f571460
parent5fd135502967fd00404ddfd237ecae4473522a42 (diff)
downloadjackson-databind-edcec24754991bcb08827b95f83bd1f37b5437c7.tar.gz
Fix #2553
-rw-r--r--release-notes/VERSION-2.x2
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java13
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java58
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java1
4 files changed, 47 insertions, 27 deletions
diff --git a/release-notes/VERSION-2.x b/release-notes/VERSION-2.x
index 0470e2e73..5270d29b8 100644
--- a/release-notes/VERSION-2.x
+++ b/release-notes/VERSION-2.x
@@ -8,6 +8,8 @@ Project: jackson-databind
#2544: java.lang.NoClassDefFoundError Thrown for compact profile1
(reported by Jon A)
+#2553: JsonDeserialize(contentAs=...) broken with raw collections
+ (reported by cpopp@github)
2.10.1 (09-Nov-2019)
diff --git a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
index 00d9e5df8..c6a3e7788 100644
--- a/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
+++ b/src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
@@ -381,12 +381,7 @@ public class TypeFactory // note: was final in 2.9, removed from 2.10
}
// A few special cases where we can simplify handling:
- // (1) Original target type has no generics -- just resolve subtype
- if (baseType.getBindings().isEmpty()) {
- newType = _fromClass(null, subclass, EMPTY_BINDINGS);
- break;
- }
- // (2) A small set of "well-known" List/Map subtypes where can take a short-cut
+ // (1) A small set of "well-known" List/Map subtypes where can take a short-cut
if (baseType.isContainerType()) {
if (baseType.isMapLikeType()) {
if ((subclass == HashMap.class)
@@ -413,6 +408,12 @@ public class TypeFactory // note: was final in 2.9, removed from 2.10
}
}
}
+ // (2) Original target type has no generics -- just resolve subtype
+ if (baseType.getBindings().isEmpty()) {
+ newType = _fromClass(null, subclass, EMPTY_BINDINGS);
+ break;
+ }
+
// (3) Sub-class does not take type parameters -- just resolve subtype
int typeParamCount = subclass.getTypeParameters().length;
if (typeParamCount == 0) {
diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
index e14ad18c2..3f016fdbe 100644
--- a/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
+++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java
@@ -190,6 +190,17 @@ public class TestValueAnnotations
}
}
+ // for [databind#2553]
+ @SuppressWarnings("rawtypes")
+ static class List2553 {
+ @JsonDeserialize(contentAs = Item2553.class)
+ public List items;
+ }
+
+ static class Item2553 {
+ public String name;
+ }
+
final static class InvalidContentClass
{
/* Such annotation not allowed, since it makes no sense;
@@ -230,10 +241,11 @@ public class TestValueAnnotations
/**********************************************************
*/
+ private final ObjectMapper MAPPER = newJsonMapper();
+
public void testOverrideClassValid() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- CollectionHolder result = m.readValue
+ CollectionHolder result = MAPPER.readValue
("{ \"strings\" : [ \"test\" ] }", CollectionHolder.class);
Collection<String> strs = result._strings;
@@ -244,9 +256,8 @@ public class TestValueAnnotations
public void testOverrideMapValid() throws Exception
{
- ObjectMapper m = new ObjectMapper();
// note: expecting conversion from number to String, as well
- MapHolder result = m.readValue
+ MapHolder result = MAPPER.readValue
("{ \"strings\" : { \"a\" : 3 } }", MapHolder.class);
Map<String,String> strs = result._data;
@@ -258,8 +269,7 @@ public class TestValueAnnotations
public void testOverrideArrayClass() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- ArrayHolder result = m.readValue
+ ArrayHolder result = MAPPER.readValue
("{ \"strings\" : [ \"test\" ] }", ArrayHolder.class);
String[] strs = result._strings;
@@ -272,7 +282,7 @@ public class TestValueAnnotations
{
// should fail due to incompatible Annotation
try {
- BrokenCollectionHolder result = new ObjectMapper().readValue
+ BrokenCollectionHolder result = MAPPER.readValue
("{ \"strings\" : [ ] }", BrokenCollectionHolder.class);
fail("Expected a failure, but got results: "+result);
} catch (JsonMappingException jme) {
@@ -288,21 +298,21 @@ public class TestValueAnnotations
public void testRootInterfaceAs() throws Exception
{
- RootInterface value = new ObjectMapper().readValue("{\"a\":\"abc\" }", RootInterface.class);
+ RootInterface value = MAPPER.readValue("{\"a\":\"abc\" }", RootInterface.class);
assertTrue(value instanceof RootInterfaceImpl);
assertEquals("abc", value.getA());
}
public void testRootInterfaceUsing() throws Exception
{
- RootString value = new ObjectMapper().readValue("\"xxx\"", RootString.class);
+ RootString value = MAPPER.readValue("\"xxx\"", RootString.class);
assertTrue(value instanceof RootString);
assertEquals("xxx", value.contents());
}
public void testRootListAs() throws Exception
{
- RootMap value = new ObjectMapper().readValue("{\"a\":\"b\"}", RootMap.class);
+ RootMap value = MAPPER.readValue("{\"a\":\"b\"}", RootMap.class);
assertEquals(1, value.size());
Object v2 = value.get("a");
assertEquals(RootStringImpl.class, v2.getClass());
@@ -311,7 +321,7 @@ public class TestValueAnnotations
public void testRootMapAs() throws Exception
{
- RootList value = new ObjectMapper().readValue("[ \"c\" ]", RootList.class);
+ RootList value = MAPPER.readValue("[ \"c\" ]", RootList.class);
assertEquals(1, value.size());
Object v2 = value.get(0);
assertEquals(RootStringImpl.class, v2.getClass());
@@ -327,8 +337,7 @@ public class TestValueAnnotations
@SuppressWarnings("unchecked")
public void testOverrideKeyClassValid() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- MapKeyHolder result = m.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
+ MapKeyHolder result = MAPPER.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
Map<StringWrapper, String> map = (Map<StringWrapper,String>)(Map<?,?>)result._map;
assertEquals(1, map.size());
Map.Entry<StringWrapper, String> en = map.entrySet().iterator().next();
@@ -343,7 +352,7 @@ public class TestValueAnnotations
{
// should fail due to incompatible Annotation
try {
- BrokenMapKeyHolder result = new ObjectMapper().readValue
+ BrokenMapKeyHolder result = MAPPER.readValue
("{ \"123\" : \"xxx\" }", BrokenMapKeyHolder.class);
fail("Expected a failure, but got results: "+result);
} catch (JsonMappingException jme) {
@@ -358,10 +367,9 @@ public class TestValueAnnotations
*/
@SuppressWarnings("unchecked")
- public void testOverrideContentClassValid() throws Exception
+ public void testOverrideContentClassValid() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- ListContentHolder result = m.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
+ ListContentHolder result = MAPPER.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
List<StringWrapper> list = (List<StringWrapper>)result._list;
assertEquals(1, list.size());
Object value = list.get(0);
@@ -371,8 +379,7 @@ public class TestValueAnnotations
public void testOverrideArrayContents() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- ArrayContentHolder result = m.readValue("{ \"data\" : [ 1, 2, 3 ] }",
+ ArrayContentHolder result = MAPPER.readValue("{ \"data\" : [ 1, 2, 3 ] }",
ArrayContentHolder.class);
Object[] data = result._data;
assertEquals(3, data.length);
@@ -384,8 +391,7 @@ public class TestValueAnnotations
public void testOverrideMapContents() throws Exception
{
- ObjectMapper m = new ObjectMapper();
- MapContentHolder result = m.readValue("{ \"map\" : { \"a\" : 9 } }",
+ MapContentHolder result = MAPPER.readValue("{ \"map\" : { \"a\" : 9 } }",
MapContentHolder.class);
Map<Object,Object> map = result._map;
assertEquals(1, map.size());
@@ -393,4 +399,14 @@ public class TestValueAnnotations
assertEquals(Integer.class, ob.getClass());
assertEquals(Integer.valueOf(9), ob);
}
+
+ // [databind#2553]
+ public void testRawListTypeContentAs() throws Exception
+ {
+ List2553 list = MAPPER.readValue("{\"items\": [{\"name\":\"item1\"}]}", List2553.class);
+ assertEquals(1, list.items.size());
+ Object value = list.items.get(0);
+ assertEquals(Item2553.class, value.getClass());
+ assertEquals("item1", ((Item2553) value).name);
+ }
}
diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
index 60bcee8dd..aba0a2830 100644
--- a/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
+++ b/src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java
@@ -282,6 +282,7 @@ public class TestTypeFactory
JavaType t = tf.constructType(ArrayList.class);
assertEquals(CollectionType.class, t.getClass());
assertSame(ArrayList.class, t.getRawClass());
+ assertSame(Object.class, ((CollectionType) t).getContentType().getRawClass());
// And then the proper way
t = tf.constructType(new TypeReference<ArrayList<String>>() { });