Skip to content

Commit

Permalink
Fix #2553
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Nov 26, 2019
1 parent 5fd1355 commit edcec24
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 27 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,12 +381,7 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
}
// 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)
Expand All @@ -413,6 +408,12 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
}
}
}
// (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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,17 @@ public void setList(List<?> l) {
}
}

// 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;
Expand Down Expand Up @@ -230,10 +241,11 @@ public void setMap(Map<Object,Object> m)
/**********************************************************
*/

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;
Expand All @@ -244,9 +256,8 @@ public void testOverrideClassValid() throws Exception

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;
Expand All @@ -258,8 +269,7 @@ public void testOverrideMapValid() throws Exception

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;
Expand All @@ -272,7 +282,7 @@ public void testOverrideClassInvalid() throws Exception
{
// 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) {
Expand All @@ -288,21 +298,21 @@ public void testOverrideClassInvalid() throws Exception

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());
Expand All @@ -311,7 +321,7 @@ public void testRootListAs() throws Exception

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());
Expand All @@ -327,8 +337,7 @@ public void testRootMapAs() throws Exception
@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();
Expand All @@ -343,7 +352,7 @@ public void testOverrideKeyClassInvalid() throws Exception
{
// 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) {
Expand All @@ -358,10 +367,9 @@ public void testOverrideKeyClassInvalid() throws Exception
*/

@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);
Expand All @@ -371,8 +379,7 @@ public void testOverrideContentClassValid() throws Exception

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);
Expand All @@ -384,13 +391,22 @@ public void testOverrideArrayContents() throws Exception

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());
Object ob = map.values().iterator().next();
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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ public void testCollections()
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>>() { });
Expand Down

0 comments on commit edcec24

Please sign in to comment.