【问题标题】:How to create the POJO to handle JSON data having array of elements as well as array of array of elements如何创建 POJO 来处理具有元素数组以及元素数组的 JSON 数据
【发布时间】:2020-06-24 08:41:28
【问题描述】:

我们有一个场景,我们有JSONs,其中一个字段有 2 个不同的值。我们想使用相同的POJO 解析所有的 json。您可以在下面找到这 2 个JSON 有效负载:

{
  "values": [
    [
      {
        "name": "item_name",
        "value": "pool"
      }
    ],
    [
      {
        "name": "item_name",
        "value": "Mob"
      }
    ]
  ],
  "name": "lines"
}

还有:

{
  "values": [
    {
      "name": "pack",
      "value": "Enter, HD"
    }
  ],
  "name": "lines"
}

目前,如果我指定 POJO 如下,第二个 json 会抛出异常

class ValuesModel extends Serializable {

  @BeanProperty
  var values: List[List[ValueModel]] = _

}

如果我如下指定 POJO,第一个 json 会抛出异常

class ValuesModel extends Serializable {

  @BeanProperty
  var values: List[ValueModel] = _

}

有没有办法创建一个POJO 来同时解析两个 json,而不是捕获异常并使用另一个模式进行解析?我正在使用Jackson 进行解析。

【问题讨论】:

    标签: java json scala jackson jackson2


    【解决方案1】:

    在这种情况下,您想要处理多个 JSON 架构并能够将其反序列化为相同的 POJO 模型,您需要实现自定义反序列化器并实现所有必需的场景。

    您可以在下面找到Java 中的示例如何反序列化JSON 有效负载:

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.core.ObjectCodec;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
    import com.fasterxml.jackson.databind.node.MissingNode;
    import com.fasterxml.jackson.databind.type.SimpleType;
    import com.fasterxml.jackson.databind.util.TokenBuffer;
    
    import java.io.File;
    import java.io.IOException;
    import java.util.Collections;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.StreamSupport;
    
    public class JsonApp {
    
        public static void main(String[] args) throws Exception {
            File jsonFile = new File("./src/main/resources/test.json");
    
            ObjectMapper mapper = new ObjectMapper();
            System.out.println(mapper.readValue(jsonFile, ValuesModel.class));
        }
    }
    
    class ValuesModelJsonDeserializer extends JsonDeserializer<List<ValueModel>> {
    
        @Override
        public List<ValueModel> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            final JsonDeserializer<Object> deserializer = ctxt.findRootValueDeserializer(SimpleType.constructUnsafe(ValueModel.class));
            final JsonNode root = p.readValueAsTree();
            // If node is a JSON object
            if (root.isObject()) {
                return Collections.singletonList(deserialize(p.getCodec(), root, deserializer, ctxt));
            }
            if (!root.isArray()) {
                // value is null or primitive
                return Collections.emptyList();
            }
    
            return StreamSupport.stream(root.spliterator(), false)
                    .map(this::unwrap)
                    .filter(node -> !node.isMissingNode())
                    .map(node -> deserialize(p.getCodec(), node, deserializer, ctxt))
                    .collect(Collectors.toList());
        }
    
        private JsonNode unwrap(JsonNode node) {
            if (node.isArray()) {
                if (node.isEmpty()) {
                    return MissingNode.getInstance();
                }
    
                return node.iterator().next();
            }
    
            return node;
        }
    
        private ValueModel deserialize(ObjectCodec codec, JsonNode value, JsonDeserializer<Object> valueDeser, DeserializationContext ctxt) {
            try (JsonParser jsonParser = createNestedParser(codec, value)) {
                return (ValueModel) valueDeser.deserialize(jsonParser, ctxt);
            } catch (IOException e) {
                throw new IllegalArgumentException(e);
            }
        }
    
        private JsonParser createNestedParser(ObjectCodec codec, JsonNode value) throws IOException {
            TokenBuffer buffer = new TokenBuffer(codec, false);
            codec.writeTree(buffer, value);
    
            JsonParser parser = buffer.asParser();
            parser.nextToken();
    
            return parser;
        }
    }
    

    要注册自定义反序列化器,您可以使用@JsonDeserialize 注解:

    @JsonDeserialize(using = ValuesModelJsonDeserializer.class)
    private List<ValueModel> values;
    

    【讨论】:

      猜你喜欢
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-06
      • 2016-12-04
      相关资源
      最近更新 更多