基于Jackson中另一个字段值的条件字段要求? [英] Conditional field requirement based on another field value in Jackson?

查看:129
本文介绍了基于Jackson中另一个字段值的条件字段要求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个带有一个字符串和两个数组的JSON表示。例如,

Consider a JSON representation with one string and two arrays. For example,

{
    "type" : "A",
    "ListA" : []
    "ListB" : [3, 4, 5]
 }

In在上述情况下,类型是必填字段,但 ListA ListB 根据 type 的值,反序列化需要有条件。换句话说,只有当 type 的值 A ListA 只有当 type 的值 B ListB c>。

In the above case, type is required field, but ListA and ListB are conditionally required for deserialization based on the value of type. In other words, ListA is only required if type had value A and ListB is only required if type had a value B.

目前,我在杰克逊和Java工作,我已经能够实现制作类型通过创建 POJO 强制字段如下:

Currently, I am working in Jackson and in Java, and I have been able to implement making type field mandatory by creating POJO as following:

public class Example {
    @JsonProperty(required = true)
    String type;

    // getter and setter auto-generated

但我不能只需将另一个 @JsonProperty(required = true)附加到 ListA ListB 因为它取决于的类型

But I can't just attach another @JsonProperty(required = true) to ListA or ListB since it's dependent on the value of type.

我如何有条件地要求 ListA ListB 用于反序列化,基于类型的值?

How can I conditionally require ListA and ListB for deserialization based on the value of type?

此外,我还将执行其他检查,例如 ListA ListB 是否为空数组( size == 0 )。

Also, I will be performing additional checks such as whether either ListA or ListB is an empty array (size == 0) or not.

推荐答案

您可以使用自定义反序列化器来实现它。

You could use a custom deserializer to achieve it.

你的示例类就像:

public class Example {

    private String type;
    private List<Integer> listA;
    private List<Integer> listB;

    // Getters and setters omitted    
}



创建一个自定义反序列化器



您的自定义反序列化器可能如下:

Creating a custom deserializer

Your custom deserializer could be as follwing:

public class ExampleDeserializer extends StdDeserializer<Example> {

    private static final String TYPE_A = "A";
    private static final String TYPE_B = "B";

    public ExampleDeserializer() {
        super(Example.class);
    }

    @Override
    public Example deserialize(JsonParser p, DeserializationContext ctxt) 
                   throws IOException, JsonProcessingException {

        ObjectMapper mapper = (ObjectMapper) p.getCodec();  
        JsonNode tree = mapper.readTree(p);  

        Example example = new Example();

        JsonNode typeNode = tree.get("type");
        if (typeNode == null || typeNode.asText().isEmpty()) {
            throw ctxt.mappingException("\"type\" is required");
        }
        example.setType(typeNode.asText());

        switch (typeNode.asText()) {

        case TYPE_A:
            ArrayNode listANode = (ArrayNode) tree.get("ListA");
            if (listANode == null || listANode.size() == 0) {
                throw ctxt.mappingException(
                           "\"ListA\" is required when \"type\" is \"" + TYPE_A + "\"");
            }
            example.setListA(createList(listANode));
            break;

        case TYPE_B:
            ArrayNode listBNode = (ArrayNode) tree.get("ListB");
            if (listBNode == null || listBNode.size() == 0) {
                throw ctxt.mappingException(
                           "\"ListB\" is required when \"type\" is \"" + TYPE_B + "\"");
            }
            example.setListB(createList(listBNode));
            break;

        default:
            throw ctxt.mappingException(
                       "\"type\" must be \"" + TYPE_A + "\" or \"" + TYPE_B + "\"");
        }


        return example;
    }

    private List<Integer> createList(ArrayNode arrayNode) {
        List<Integer> list = new ArrayList<Integer>();
        for (JsonNode node : arrayNode) {
            list.add(node.asInt());
        }
        return list;
    }
}



注册自定义反序列化器



将上面定义的自定义反序列化器注册到 ObjectMapper

SimpleModule module = new SimpleModule("ExampleDeserializer", 
        new Version(1, 0, 0, null, "com.example", "example-deserializer")); 

ExampleDeserializer exampleDeserializer = new ExampleDeserializer();
module.addDeserializer(Example.class, exampleDeserializer);

ObjectMapper mapper = new ObjectMapper()
                          .registerModule(module)
                          .enable(SerializationFeature.INDENT_OUTPUT);



测试自定义反序列化器



使用自定义序列化程序:

Testing your custom deserializer

Use the custom serializer:

String json = "{\"type\":\"A\",\"ListA\":[1,2,3]}";
Example example = mapper.readValue(json, Example.class);

这篇关于基于Jackson中另一个字段值的条件字段要求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆