3

I'd like to map a JSON to POJO. The JSON format is:

{
    user: "123abc",
    messages: [
        {"type":"A", "args": {"a":"str", "b":0} },
        {"type":"B", "args": {"c":true, "d":false} },
        ...
    ]
}

Each type of message has its own expected args. For example:

class TypeAMessage extends Message {
    String a;
    int b;
}

class TypeBMessage extends Message {
    boolean c;
    boolean d;
}

I could map this JSON to a simple POJO like:

class Messages {
    @JsonProperty("user")
    String user;
    @JsonProperty("messageList")
    List<Message> messageList;

    class Message {
        @JsonProperty("type")
        String type;
        @JsonProperty("args")
        Map<String, Object> args;
    }
}

But this doesn't seem ideal, because args can contain multiple variable types (String, Integer, ...) and now they're all being stored as a general Object variable.

I already know what args to expect based on the message type. Since each type expects a different set of arguments, I thought of mapping the JSON to a class like this:

class Messages {
    @JsonProperty("user")
    String user;

    @JsonProperty("messageList")
    List<? extends Message> messageList;

    class Message {}

    class TypeAMessage extends Message {
        @JsonProperty("a")
        String a;
        @JsonProperty("b")
        int b;
    }

    class TypeBMessage extends Message {
        @JsonProperty("c")
        boolean c;
        @JsonProperty("d")
        boolean d;
    }
}

I'm using Jackson JSON, and JSON-to-object conversion fails with Unrecognized field "a" (and b, c, d too) because these fields are not in the parent Message class.

Am I going about this the wrong way? Or is there a way to contain each Message Child object, by telling the JSON Object Mapper to look for children to map to?

2
  • 1
    Possible duplicate of Json deserialization into another class hierarchy using Jackson Commented Mar 11, 2016 at 9:15
  • @mlk Thanks for the link. I dug thru the link contents (and the link's links' contents) and found a solution. The solution is only a few lines on top of what's written in the question, and appears to be simpler than what is asked in your link. So I think it's helpful to keep this question open and answer it myself. If you don't disagree then I will follow through. Commented Mar 12, 2016 at 0:27

2 Answers 2

2

The solution is to add some annotations onto Message so that the JSON deserializer knows what subclass of Message to use:

class Messages {
    @JsonProperty("user")
    String user;

    @JsonProperty("messageList")
    List<Message> messageList;


    @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY, 
            property="type")
    @JsonSubTypes( {
            @JsonSubTypes.Type(value=TypeAMessage.class, name="typeA"),
            @JsonSubTypes.Type(value=TypeBMessage.class, name="typeB")
    })

    static class Message {}

    static class TypeAMessage extends Message {
        @JsonProperty("a")
        String a;
        @JsonProperty("b")
        int b;
    }

    static class TypeBMessage extends Message {
        @JsonProperty("c")
        boolean c;
        @JsonProperty("d")
        boolean d;
    }
}

Example JSON message that specifies the subclass to use:

{
    "user":"someUser",
    "messageList":[
        {"type":"typeA", "a":"someStr", "b":123}, 
        {"type":"typeB", "c":false, "d":true}
    ]
}
Sign up to request clarification or add additional context in comments.

Comments

0

Try make inner class static

static class TypeAMessage extends Message {
    @JsonProperty("a")
    String a;
    @JsonProperty("b")
    int b;
}

static class TypeBMessage extends Message {
    @JsonProperty("c")
    boolean c;
    @JsonProperty("d")
    boolean d;
}

1 Comment

Thanks though this does not solve the issue. Please refer to the answer I posted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.