Moshe Katz
Moshe Katz

Reputation: 16873

Jackson incorrectly deserializing nested object's values into parent

I have the following JSON file which I am trying to deserialize:

{
    "name": "ComponentX",
    "implements": ["Temperature.Sensor"],
    "requires": [
        {"type": "interface", "name": "Temperature.Thermostat", "execute": [
            "../Thermostat.exe"
        ]}
    ]
}

It is a description of a component in a code sample for a distributed system.

Here is the class that this is supposed to deserialize to:

public class ComponentDescription {
    @JsonProperty("name")
    public String Name;

    @JsonProperty("implements")
    public String[] Implements;

    @JsonProperty("requires")
    public ComponentDependency[] Requires;

    @JsonIgnore
    public String RabbitConnectionName;

    private static final ObjectMapper mapper = new ObjectMapper();

    public static ComponentDescription FromJSON(String json)
        throws JsonParseException, JsonMappingException, IOException
    {
        return mapper.readValue(json, ComponentDescription.class);
    }

    public class ComponentDependency
    {
        @JsonCreator
        public ComponentDependency() {
            // Need an explicit default constructor in order to use Jackson.
        }

        @JsonProperty("type")
        public DependencyType Type;

        @JsonProperty("name")
        public String Name;

        /**
         * A list of ways to start the required component if it is not already running.
         */
        @JsonProperty("execute")
        public String[] Execute;
    }

    /**
     * A dependency can either be on "some implementation of an interface" or it
     * can be "a specific component", regardless of what other interface implementations
     * may be available.
     */
    public enum DependencyType
    {
        Interface,
        Component
    }
}

When I run ComponentDescription.FromJSON(jsonData), which uses the Jackson ObjectMapper to deserialize the JSON into the appropriate classes, I get the following exception:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "type" (class edu.umd.cs.seam.dispatch.ComponentDescription), not marked as ignorable (3 known properties: , "implements", "name", "requires"])
 at [Source: java.io.StringReader@39346e64; line: 1, column: 103] (through reference chain: edu.umd.cs.seam.dispatch.ComponentDescription["requires"]->edu.umd.cs.seam.dispatch.ComponentDescription["type"])

It seems that Jackson is trying to deserialize the requires array in the JSON object as an array of ComponentDescription instead of an array of ComponentDependency. How do I get it to use the correct class? I would prefer an answer that gets Jackson to look at the type of public ComponentDependency[] Requires and see use it automatically over an answer that requires me to put the type name in again somewhere else (such as an @ attribute).

Upvotes: 0

Views: 1514

Answers (1)

fge
fge

Reputation: 121710

My guess is that the problem comes from ComponentDependency not being static. As it is not declared static, it means it can only be instantiated with an existing instance of ComponentDescription.

For more details, see here.

Upvotes: 3

Related Questions