question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Unable to deserialize collection of concrete subclass when using defaultImpl

See original GitHub issue

This worked in the last 2.7, but is broken in both 2.8.0 and 2.8.5.

I have a field parameterized with a concrete subclass of a base class annotated with @JsonTypeInfo, and I am trying to deserialize a collection that contains only that specific class. In 2.8.x, the readValue method fails with com.fasterxml.jackson.databind.JsonMappingException: Class JacksonSubclassCollectionTest$SomeBaseClass not subtype of [simple type, class JacksonSubclassCollectionTest$SomeSubClass]. This doesn’t appear to happen without defaultImpl (but I have legacy data with no type field that I need to be able to keep deserializing in other contexts). Full stack trace follows example.

public class JacksonSubclassCollectionTest {
  public static void main(String[] args) throws Exception {
    ObjectMapper mapper = new ObjectMapper();

    SomeContainer container = mapper.readValue("{\"collection\":[{\"type\":\"SUBCLASS\",\"field\":7}]}", SomeContainer.class);

    System.out.println(container.collection.get(0).field);
  }

  @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", defaultImpl = SomeBaseClass.class, visible = true)
  @JsonSubTypes({@JsonSubTypes.Type(name = "SUBCLASS", value = SomeSubClass.class)})
  public static class SomeBaseClass {
    @JsonTypeId
    public String type;
  }

  public static class SomeSubClass extends SomeBaseClass {
    public int field;
  }

  public static class SomeContainer {
    public ArrayList<SomeSubClass> collection;
  }
}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Class JacksonSubclassCollectionTest$SomeBaseClass not subtype of [simple type, class JacksonSubclassCollectionTest$SomeSubClass]
 at [Source: {"collection":[{"type":"SUBCLASS","field":7}]}; line: 1, column: 1]
	at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:296)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
	at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
	at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
	at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
	at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
	at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
	at JacksonSubclassCollectionTest.main(JacksonSubclassCollectionTest.java:20)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.IllegalArgumentException: Class JacksonSubclassCollectionTest$SomeBaseClass not subtype of [simple type, class JacksonSubclassCollectionTest$SomeSubClass]
	at com.fasterxml.jackson.databind.type.TypeFactory.constructSpecializedType(TypeFactory.java:359)
	at com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder.buildTypeDeserializer(StdTypeResolverBuilder.java:118)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findTypeDeserializer(BasicDeserializerFactory.java:1363)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findPropertyContentTypeDeserializer(BasicDeserializerFactory.java:1526)
	at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.resolveMemberAndTypeAnnotations(BasicDeserializerFactory.java:1841)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.constructSettableProperty(BeanDeserializerFactory.java:735)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.addBeanProps(BeanDeserializerFactory.java:520)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:226)
	at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
	at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
	... 12 more

Issue Analytics

  • State:open
  • Created 7 years ago
  • Reactions:1
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
blopcommented, Nov 22, 2017

Guys, this is a BIG regression for people upgrading from 2.7.

If you have some class with a List<> and another with a Set<>, using a SimpleAbstractTypeResolver that provides the defaultImpl as ArrayList and HashSet, it just does NOT work anymore.

0reactions
KroligGcommented, Feb 20, 2019

Look like this is fixed by https://github.com/FasterXML/jackson-databind/issues/1565. At least updating to 2.9.6 fixed same issue for me.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Jackson deserialization to concrete polymorphic class
There's a default implementation class to use for deserialization via defaultImpl : @JsonTypeInfo(use = JsonTypeInfo.
Read more >
Using @JsonTypeInfo and @JsonSubTypes, Deserialize an ...
I have found a solution. You need to enable MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL in order to directly deserialize the object using concrete subclass ...
Read more >
How To Deserialize Subclasses Using ObjectMapper
Deserialize JSON to the abstract class using Its child classes or deserialize in subclasses using Jackson Object mapper.
Read more >
Deserializing an interface with Jackson | Andrew Tarry
Using Java and json together can make it hard to manage deserialisation correctly when using interfaces. Here we show the solution to 3...
Read more >
SUSE-SU-2022:1678-1: important: Security update for jackson ...
READ_ONLY' fails with collections when a property name is specified + ... thrown for mismatched subclass deserialization + Add convenience ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found