Skip to content

Commit edcec24

Browse files
committed
Fix #2553
1 parent 5fd1355 commit edcec24

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Project: jackson-databind
88

99
#2544: java.lang.NoClassDefFoundError Thrown for compact profile1
1010
(reported by Jon A)
11+
#2553: JsonDeserialize(contentAs=...) broken with raw collections
12+
(reported by cpopp@github)
1113

1214
2.10.1 (09-Nov-2019)
1315

src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java

+7-6
Original file line numberDiff line numberDiff line change
@@ -381,12 +381,7 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
381381
}
382382
// A few special cases where we can simplify handling:
383383

384-
// (1) Original target type has no generics -- just resolve subtype
385-
if (baseType.getBindings().isEmpty()) {
386-
newType = _fromClass(null, subclass, EMPTY_BINDINGS);
387-
break;
388-
}
389-
// (2) A small set of "well-known" List/Map subtypes where can take a short-cut
384+
// (1) A small set of "well-known" List/Map subtypes where can take a short-cut
390385
if (baseType.isContainerType()) {
391386
if (baseType.isMapLikeType()) {
392387
if ((subclass == HashMap.class)
@@ -413,6 +408,12 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
413408
}
414409
}
415410
}
411+
// (2) Original target type has no generics -- just resolve subtype
412+
if (baseType.getBindings().isEmpty()) {
413+
newType = _fromClass(null, subclass, EMPTY_BINDINGS);
414+
break;
415+
}
416+
416417
// (3) Sub-class does not take type parameters -- just resolve subtype
417418
int typeParamCount = subclass.getTypeParameters().length;
418419
if (typeParamCount == 0) {

src/test/java/com/fasterxml/jackson/databind/deser/TestValueAnnotations.java

+37-21
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,17 @@ public void setList(List<?> l) {
190190
}
191191
}
192192

193+
// for [databind#2553]
194+
@SuppressWarnings("rawtypes")
195+
static class List2553 {
196+
@JsonDeserialize(contentAs = Item2553.class)
197+
public List items;
198+
}
199+
200+
static class Item2553 {
201+
public String name;
202+
}
203+
193204
final static class InvalidContentClass
194205
{
195206
/* Such annotation not allowed, since it makes no sense;
@@ -230,10 +241,11 @@ public void setMap(Map<Object,Object> m)
230241
/**********************************************************
231242
*/
232243

244+
private final ObjectMapper MAPPER = newJsonMapper();
245+
233246
public void testOverrideClassValid() throws Exception
234247
{
235-
ObjectMapper m = new ObjectMapper();
236-
CollectionHolder result = m.readValue
248+
CollectionHolder result = MAPPER.readValue
237249
("{ \"strings\" : [ \"test\" ] }", CollectionHolder.class);
238250

239251
Collection<String> strs = result._strings;
@@ -244,9 +256,8 @@ public void testOverrideClassValid() throws Exception
244256

245257
public void testOverrideMapValid() throws Exception
246258
{
247-
ObjectMapper m = new ObjectMapper();
248259
// note: expecting conversion from number to String, as well
249-
MapHolder result = m.readValue
260+
MapHolder result = MAPPER.readValue
250261
("{ \"strings\" : { \"a\" : 3 } }", MapHolder.class);
251262

252263
Map<String,String> strs = result._data;
@@ -258,8 +269,7 @@ public void testOverrideMapValid() throws Exception
258269

259270
public void testOverrideArrayClass() throws Exception
260271
{
261-
ObjectMapper m = new ObjectMapper();
262-
ArrayHolder result = m.readValue
272+
ArrayHolder result = MAPPER.readValue
263273
("{ \"strings\" : [ \"test\" ] }", ArrayHolder.class);
264274

265275
String[] strs = result._strings;
@@ -272,7 +282,7 @@ public void testOverrideClassInvalid() throws Exception
272282
{
273283
// should fail due to incompatible Annotation
274284
try {
275-
BrokenCollectionHolder result = new ObjectMapper().readValue
285+
BrokenCollectionHolder result = MAPPER.readValue
276286
("{ \"strings\" : [ ] }", BrokenCollectionHolder.class);
277287
fail("Expected a failure, but got results: "+result);
278288
} catch (JsonMappingException jme) {
@@ -288,21 +298,21 @@ public void testOverrideClassInvalid() throws Exception
288298

289299
public void testRootInterfaceAs() throws Exception
290300
{
291-
RootInterface value = new ObjectMapper().readValue("{\"a\":\"abc\" }", RootInterface.class);
301+
RootInterface value = MAPPER.readValue("{\"a\":\"abc\" }", RootInterface.class);
292302
assertTrue(value instanceof RootInterfaceImpl);
293303
assertEquals("abc", value.getA());
294304
}
295305

296306
public void testRootInterfaceUsing() throws Exception
297307
{
298-
RootString value = new ObjectMapper().readValue("\"xxx\"", RootString.class);
308+
RootString value = MAPPER.readValue("\"xxx\"", RootString.class);
299309
assertTrue(value instanceof RootString);
300310
assertEquals("xxx", value.contents());
301311
}
302312

303313
public void testRootListAs() throws Exception
304314
{
305-
RootMap value = new ObjectMapper().readValue("{\"a\":\"b\"}", RootMap.class);
315+
RootMap value = MAPPER.readValue("{\"a\":\"b\"}", RootMap.class);
306316
assertEquals(1, value.size());
307317
Object v2 = value.get("a");
308318
assertEquals(RootStringImpl.class, v2.getClass());
@@ -311,7 +321,7 @@ public void testRootListAs() throws Exception
311321

312322
public void testRootMapAs() throws Exception
313323
{
314-
RootList value = new ObjectMapper().readValue("[ \"c\" ]", RootList.class);
324+
RootList value = MAPPER.readValue("[ \"c\" ]", RootList.class);
315325
assertEquals(1, value.size());
316326
Object v2 = value.get(0);
317327
assertEquals(RootStringImpl.class, v2.getClass());
@@ -327,8 +337,7 @@ public void testRootMapAs() throws Exception
327337
@SuppressWarnings("unchecked")
328338
public void testOverrideKeyClassValid() throws Exception
329339
{
330-
ObjectMapper m = new ObjectMapper();
331-
MapKeyHolder result = m.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
340+
MapKeyHolder result = MAPPER.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class);
332341
Map<StringWrapper, String> map = (Map<StringWrapper,String>)(Map<?,?>)result._map;
333342
assertEquals(1, map.size());
334343
Map.Entry<StringWrapper, String> en = map.entrySet().iterator().next();
@@ -343,7 +352,7 @@ public void testOverrideKeyClassInvalid() throws Exception
343352
{
344353
// should fail due to incompatible Annotation
345354
try {
346-
BrokenMapKeyHolder result = new ObjectMapper().readValue
355+
BrokenMapKeyHolder result = MAPPER.readValue
347356
("{ \"123\" : \"xxx\" }", BrokenMapKeyHolder.class);
348357
fail("Expected a failure, but got results: "+result);
349358
} catch (JsonMappingException jme) {
@@ -358,10 +367,9 @@ public void testOverrideKeyClassInvalid() throws Exception
358367
*/
359368

360369
@SuppressWarnings("unchecked")
361-
public void testOverrideContentClassValid() throws Exception
370+
public void testOverrideContentClassValid() throws Exception
362371
{
363-
ObjectMapper m = new ObjectMapper();
364-
ListContentHolder result = m.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
372+
ListContentHolder result = MAPPER.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class);
365373
List<StringWrapper> list = (List<StringWrapper>)result._list;
366374
assertEquals(1, list.size());
367375
Object value = list.get(0);
@@ -371,8 +379,7 @@ public void testOverrideContentClassValid() throws Exception
371379

372380
public void testOverrideArrayContents() throws Exception
373381
{
374-
ObjectMapper m = new ObjectMapper();
375-
ArrayContentHolder result = m.readValue("{ \"data\" : [ 1, 2, 3 ] }",
382+
ArrayContentHolder result = MAPPER.readValue("{ \"data\" : [ 1, 2, 3 ] }",
376383
ArrayContentHolder.class);
377384
Object[] data = result._data;
378385
assertEquals(3, data.length);
@@ -384,13 +391,22 @@ public void testOverrideArrayContents() throws Exception
384391

385392
public void testOverrideMapContents() throws Exception
386393
{
387-
ObjectMapper m = new ObjectMapper();
388-
MapContentHolder result = m.readValue("{ \"map\" : { \"a\" : 9 } }",
394+
MapContentHolder result = MAPPER.readValue("{ \"map\" : { \"a\" : 9 } }",
389395
MapContentHolder.class);
390396
Map<Object,Object> map = result._map;
391397
assertEquals(1, map.size());
392398
Object ob = map.values().iterator().next();
393399
assertEquals(Integer.class, ob.getClass());
394400
assertEquals(Integer.valueOf(9), ob);
395401
}
402+
403+
// [databind#2553]
404+
public void testRawListTypeContentAs() throws Exception
405+
{
406+
List2553 list = MAPPER.readValue("{\"items\": [{\"name\":\"item1\"}]}", List2553.class);
407+
assertEquals(1, list.items.size());
408+
Object value = list.items.get(0);
409+
assertEquals(Item2553.class, value.getClass());
410+
assertEquals("item1", ((Item2553) value).name);
411+
}
396412
}

src/test/java/com/fasterxml/jackson/databind/type/TestTypeFactory.java

+1
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ public void testCollections()
282282
JavaType t = tf.constructType(ArrayList.class);
283283
assertEquals(CollectionType.class, t.getClass());
284284
assertSame(ArrayList.class, t.getRawClass());
285+
assertSame(Object.class, ((CollectionType) t).getContentType().getRawClass());
285286

286287
// And then the proper way
287288
t = tf.constructType(new TypeReference<ArrayList<String>>() { });

0 commit comments

Comments
 (0)