杰克逊根据类型反序列化

新手上路,请多包涵

假设我有以下格式的 JSON:

 {
    "type" : "Foo"
    "data" : {
        "object" : {
            "id" : "1"
            "fizz" : "bizz"
            ...
        },
        "metadata" : {
            ...
        },
        "owner" : {
            "name" : "John"
            ...
        }
    }
}

我试图避免自定义反序列化器并尝试将上述 JSON(称为 Wrapper.java)反序列化为 Java POJO。 “类型”字段指示“对象”反序列化,即。 type = foo 表示使用 Foo.java 反序列化“对象”字段。 (如果 type = Bar,则使用 Bar.java 反序列化对象字段)。元数据/所有者将始终使用一个简单的 Jackson 注释 Java 类以相同的方式反序列化每个。有没有办法使用注释来完成这个?如果没有,如何使用自定义反序列化器完成此操作?

原文由 John Baum 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 535
2 个回答

仅注释方法

作为 自定义反序列化器方法的替代方案,您可以使用以下方法作为仅注释解决方案(类似于 Spunc 的回答 中描述的解决方案,但使用 type 作为 外部属性):

 public abstract class AbstractData {

    private Owner owner;

    private Metadata metadata;

    // Getters and setters
}

 public static final class FooData extends AbstractData {

    private Foo object;

    // Getters and setters
}

 public static final class BarData extends AbstractData {

    private Bar object;

    // Getters and setters
}

 public class Wrapper {

    private String type;

    @JsonTypeInfo(use = Id.NAME, property = "type", include = As.EXTERNAL_PROPERTY)
    @JsonSubTypes(value = {
            @JsonSubTypes.Type(value = FooData.class, name = "Foo"),
            @JsonSubTypes.Type(value = BarData.class, name = "Bar")
    })
    private AbstractData data;

    // Getters and setters
}

在这种方法中, @JsonTypeInfo 设置为使用 type 作为 外部属性 来确定正确的类来映射 data 属性。

JSON 文档可以反序列化如下:

 ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);

原文由 cassiomolin 发布,翻译遵循 CC BY-SA 4.0 许可协议

自定义解串器方法

您可以使用自定义反序列化程序来检查 type 属性以将 object 属性解析为最合适的类。

首先定义一个接口,将由 FooBar 类实现:

 public interface Model {

}

 public class Foo implements Model {

    // Fields, getters and setters
}

 public class Bar implements Model {

    // Fields, getters and setters
}

然后定义你的 WrapperData 类:

 public class Wrapper {

    private String type;

    private Data data;

    // Getters and setters
}

 public class Data {

    @JsonDeserialize(using = ModelDeserializer.class)
    private Model object;

    private Metadata metadata;

    private Owner owner;

    // Getters and setters
}

object 字段用 @JsonDeserialize 注释,指示将用于 object 属性的反序列化器。

解串器定义如下:

 public class ModelDeserializer extends JsonDeserializer<Model> {

    @Override
    public Model deserialize(JsonParser jp, DeserializationContext ctxt)
        throws IOException, JsonMappingException {

        // Get reference to ObjectCodec
        ObjectCodec codec = jp.getCodec();

        // Parse "object" node into Jackson's tree model
        JsonNode node = codec.readTree(jp);

        // Get value of the "type" property
        String type = ((Wrapper) jp.getParsingContext().getParent()
            .getCurrentValue()).getType();

        // Check the "type" property and map "object" to the suitable class
        switch (type) {

            case "Foo":
                return codec.treeToValue(node, Foo.class);

            case "Bar":
                return codec.treeToValue(node, Bar.class);

            default:
                throw new JsonMappingException(jp,
                    "Invalid value for the \"type\" property");
        }
    }
}

JSON 文档可以反序列化如下:

 ObjectMapper mapper = new ObjectMapper();
Wrapper wrapper = mapper.readValue(json, Wrapper.class);

作为此自定义反序列化器的替代方案,请考虑使用 仅注释方法

原文由 cassiomolin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题