Skip to content
This repository has been archived by the owner on Jan 22, 2019. It is now read-only.

When using JAXB annotations only, Jackson doesn't include any type metadata for inheritance hierarchies when serializing to JSON (or XML) #71

Open
jo-ka opened this issue Jun 27, 2018 · 0 comments

Comments

@jo-ka
Copy link

jo-ka commented Jun 27, 2018

The situation I face has already been described twice by the same person in two different threads, on Stack Overflow and Google Groups. Unfortunately, it looks like they never raised an issue, so here it goes:

I'm stuck with serializing Beans using Jackson that carry only JAXB annotations, as they're generated from XSD. I have a type hierarchy that basically looks like this (copied from said threads, with the only difference that my ParentClass also has an @XmlSeeAlso annotation):

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ParentClass", propOrder = { "parentField" })
@XmlSeeAlso( { ChildAClass.class, ChildBClass.class } )
public class ParentClass {

    @XmlElement(name = "ParentField")
    protected String parentField;

    // getters and setters here
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ChildAClass", propOrder = { "childAfield" })
public class ChildAClass extends ParentClass {

    @XmlElement(name = "ChildAfield")
    protected String childAfield;

    // getters and setters here
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ChildBClass", propOrder = { "childBfield" })
public class ChildBClass extends ParentClass {

    @XmlElement(name = "ChildBfield")
    protected String childBfield;

    // getters and setters here
}

The resulting JSON basically looks like this when serializing a ChildAClass:

{
  "ChildAfield": "child A field",
  "ParentField": "..."
}

and analogously like this when serializing a ChildBClass:

{
  "ChildBfield": "child B field",
  "ParentField": "..."
}

The problem is that there's no type metadata generated into the JSON objects, so if one wanted to deserialize this result, one would run into an exception like described in the linked threads:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ChildAfield" (class inheritance.model.ParentClass), not marked as ignorable (one known property: "ParentField"])
 at [Source: src/test/resources/testfiles/json/inheritance.json; line: 2, column: 19] (through reference chain: inheritance.model.ParentClass["ChildAfield"])
    at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:79)
    at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty( ...

In fact, I'm not deserializing the resulting JSON myself again but this is consumed by an Android client. But the lack of type metadata poses a problem for any consuming client (unless they are willing to/capable of inspecting the properties that are present and deduce the type from that...).

As a sidenote, if I choose to serialize to XML instead of JSON, type metadata is missing all the same.

As suggested in the thread on Google Groups, I added @JsonTypeInfo manually into the generated classes to see if that works, and indeed this leads to the type metadata being included in the resulting JSON.

I've worked with EclipseLink MOXy before to serialize beans to JSON/XML, therefore I know that there is at least one standard way to include type metadata in XML with JAXB using xsi:type, which is for example described here. If I use MOXy to serialize to JSON instead of XML with this approach, MOXy merely includes a type property in the result, too, preserving the type metadata. MOXy also has its own proprietary extensions to control type metadata with @XmlDiscriminatorNode/@XmlDiscriminatorValue, and there are other ways still. But it would be nice if Jackson at least produced something by default, if only JAXB annotations can be used.

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

1 participant