使用生成的类和Jackson来读取JSON数据流到对象

时间:2017-11-13 20:20:58

标签: java json jackson

我已经从Swagger定义生成了类。共有4个不同的类,其中一个字段是共同的op(没有类层次结构,每个类中都会复制该字段)。

我希望根据op字段的值将JSON数据流反序列化为4个不同类别中的一个。

例如:

{"op": "typeA", ...} -> generates TypeA
{"op": "typeB", ...} -> generates TypeB

我想用Jackson来做这件事。我遇到的问题是我发现的所有示例都假定您能够修改原始类,以便您可以创建类层次结构来解决问题。但是我的问题是如何在不修改原始类的情况下解决这个问题?

原始示例采用层次结构,并按以下方式执行:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property = "op",
        visible = true)
@JsonSubTypes({
        @JsonSubTypes.Type(value = ConnectionMessage.class, name = "connection"),
        @JsonSubTypes.Type(value = StatusMessage.class, name = "status"),
        @JsonSubTypes.Type(value = MarketChangeMessage.class, name = "mcm"),
        @JsonSubTypes.Type(value = OrderChangeMessage.class, name = "ocm"),
})
public interface MixInResponseMessage {

}

1 个答案:

答案 0 :(得分:1)

这可以使用带有switch-case语句的自定义反序列化器来完成,以根据“op”字段的值解析正确的类型:

class OpDeserializer extends JsonDeserializer {
    private final ObjectMapper mapper = new ObjectMapper();

    @Override
    public Object deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        final JsonNode node = jsonParser.readValueAsTree();
        final String op = node.get("op").asText();
        switch (op) {
            case "typeA": return mapper.treeToValue(node, TypeA.class);
            case "typeB": return mapper.treeToValue(node, TypeB.class);
            default: return mapper.treeToValue(node, Object.class);
        }
    }
}

请注意ObjectMapper字段如何用于将TreeNode转换为所需类型的对象。

这不需要TypeATypeB等除Object以外的任何其他常见父级。

有必要将此反序列化器指定为用于具有"op"字段的每个JSON元素。我通过解析这个类来测试:

class Ops {
    @JsonDeserialize(contentUsing = OpDeserializer.class)
    Object[] ops;
}