Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonTypeInfo ignored when serializing a plain list #1816

Closed
dweiss opened this issue Nov 8, 2017 · 5 comments
Closed

JsonTypeInfo ignored when serializing a plain list #1816

dweiss opened this issue Nov 8, 2017 · 5 comments

Comments

@dweiss
Copy link

dweiss commented Nov 8, 2017

JsonTypeInfo seems to be ignored entirely if the serialized value is a list (and not embedded in another bean). This is present with the most recent 2.8.9.

Repro:

public class TypeSerializationTest {
  @JsonTypeInfo(
      use = JsonTypeInfo.Id.NAME,
      property = "type")
  @JsonSubTypes({
    @JsonSubTypes.Type(name = "sub1", value = Sub1.class),
    @JsonSubTypes.Type(name = "sub2", value = Sub2.class)})
  public static class Superclass {}
  
  public static class Sub1 extends Superclass {}
  public static class Sub2 extends Superclass {}
  
  class ListHolder {
    @JsonProperty
    ArrayList<Superclass> list;
  }

  @Test
  public void testRoundtripClassName() throws IOException {
    ArrayList<Superclass> list = new ArrayList<>(Arrays.asList(
        new Sub1(),
        new Sub2()));

    
    ListHolder foo = new ListHolder();
    foo.list = list;

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(foo));
    System.out.println(mapper.writeValueAsString(foo.list));
  }
}

Produces this:

{"list":[{"type":"sub1"},{"type":"sub2"}]}
[{},{}]

I'd expect the second line to have the 'type' property information as well?

@cowtowncoder
Copy link
Member

Ok, this needs to go in FAQ. It gets asked on monthly basis. :)

Yes, this is as expected: the only type that Jackson can see (due to Java Type Erasure) is ArrayList<?>. Since ? is about same as Object, and has no polymorphic type indicators, type is not listed. Same applies to all generic types, but not all Lists (or Maps etc).

There are couple of work-arounds here:

  1. Remove generic-ness by sub-typing, using:

    public class MyFooList extends ArrayList { }

  2. Specifying type information on write call:

    mapper.writerFor(new TypeReference<List>() { })
    .writeValueAsString();

both of which work. But in general it may be best to simply avoid use of generic types as root value if possible.

@dweiss
Copy link
Author

dweiss commented Nov 8, 2017

Uh, apologies -- I did scan the bug database, but didn't find it somehow.

I understand why it doesn't work, but still think it's confusing as hell: my assumption was that if the polymorphic tags were specified on the contents of a list, they would be retrieved from each element upon serialization. I see how this can be a challenge on deserialization though (if the typing information isn't globally unique, such as a class name).

@cowtowncoder
Copy link
Member

@dweiss There are many reports, but since this is not really a bug but feature it's difficult to find issues. I really need to spend time documenting this as FAQ.

As to handling: per-element determination is not made due to a few different reasons

  1. Performance: doing lookup for every element would be prohibitively expensive
  2. Deserialization: if different subtypes could have different settings (like inclusion, name vs class, property name) it would not be possible (or at least feasible) to really determine what rule to use.

Of these (2) is bigger. Effectively all elements of a container type (Collection, array, Map) must have same base type, configuration of which is used for all elements.

@dweiss
Copy link
Author

dweiss commented Nov 8, 2017

Yup, clear. Thank you and sorry for the noise.

@cowtowncoder
Copy link
Member

@dweiss No problem at all. I can see how this is surprising and sub-optimal. I just would like to make it easier to figure this out since it is quite intricate. And I may be one of few people who know it fully, having implemented the system... took a while and is partly complicated due to configurability of various aspect.

@FasterXML FasterXML deleted a comment from caeus Nov 10, 2021
@FasterXML FasterXML locked as resolved and limited conversation to collaborators Nov 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants