diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2019-11-26 15:29:17 -0800 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2019-11-26 15:29:17 -0800 |
commit | edcec24754991bcb08827b95f83bd1f37b5437c7 (patch) | |
tree | 6b8a4a6d2eb628c3c772ad0dea26d2050f571460 | |
parent | 5fd135502967fd00404ddfd237ecae4473522a42 (diff) | |
download | jackson-databind-edcec24754991bcb08827b95f83bd1f37b5437c7.tar.gz |
Fix #2553
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>>() { }); |