【问题标题】:Converting Json to Java Object containing variable of type (some subclass)将 Json 转换为包含类型变量的 Java 对象(某些子类)
【发布时间】:2016-03-11 07:09:37
【问题描述】:

我想将 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 可以包含多种变量类型(字符串、整数、...),现在它们都被存储为一般的Object 变量。

根据消息type,我已经知道预期的参数。由于每个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 类中。

我是不是走错了路?或者有没有办法通过告诉 JSON 对象映射器寻找要映射到的子对象来包含每个消息子对象?

【问题讨论】:

  • @mlk 感谢您的链接。我挖掘了链接内容(以及链接的链接内容)并找到了解决方案。解决方案只是问题中所写内容的几行,并且似乎比链接中所要求的更简单。所以我认为让这个问题保持开放并自己回答是有帮助的。如果你不反对,那么我会坚持下去。

标签: java json jackson


【解决方案1】:

解决方案是在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}
    ]
}

【讨论】:

    【解决方案2】:

    尝试将内部类设为静态

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

    【讨论】:

    • 谢谢,虽然这并不能解决问题。请参考我发布的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多