将Json转换为包含类型变量的Java Object(某些子类)

时间:2016-03-11 07:09:37

标签: java json jackson

我想将JSON映射到POJO。 JSON格式为:

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

每种类型的消息都有自己的预期参数。例如:

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

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

我可以将这个JSON映射到一个简单的POJO:

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

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

但这似乎并不理想,因为args可以包含多个变量类型(String,Integer,...),现在它们都被存储为一般的Object变量。< / p>

根据消息type,我已经知道了预期的args。由于每个type都需要一组不同的参数,我想到将JSON映射到这样的类:

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;
    }
}

我正在使用Jackson JSON,并且JSON到对象的转换失败了Unrecognized field "a"(以及b,c,d),因为这些字段不在父Message类中。

我是以错误的方式来做这件事的吗?或者有没有办法包含每个Message Child对象,告诉JSON Object Mapper寻找要映射到的子节点?

2 个答案:

答案 0 :(得分:0)

尝试使内部类静态

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 :(得分:0)

解决方案是在Message上添加一些注释,以便JSON反序列化器知道要使用的Message的子类:

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;
    }
}

示例JSON消息,指定要使用的子类:

{
    "user":"someUser",
    "messageList":[
        {"type":"typeA", "a":"someStr", "b":123}, 
        {"type":"typeB", "c":false, "d":true}
    ]
}