【问题标题】:Deserializing json to pojo where json field has different data types将 json 反序列化为 pojo,其中 json 字段具有不同的数据类型
【发布时间】:2021-08-18 14:16:32
【问题描述】:

我正在尝试将 json 反序列化为 java pojo,但我不知道应该如何开始创建一个可用于反序列化 json 的 java 对象,如下所示:

{
    "links": [],
    "version": 2,
    "executionState": "completed",
    "outputs": [
        {
            "name": "identifier",
            "value": "2411"
        },
        {
            "name": "segment",
            "value": "COMPLEX"
        },
        {
            "name": "rules",
            "value": [
                {
                    "metadata": [
                        {
                            "ID": "int"
                        },
                        {
                            "NAME": "string"
                        },
                    ]
                },
                {
                    "data": [
                        [
                            2,
                            "S1"
                        ],
                        [
                            21,
                            "S6"
                        ]
                    ]
                }
            ]
        }
    ]
}

我正在与杰克逊合作,并希望使用这样的东西: MyPojo 响应 = mapper.readValue(jsonString, MyPojo.class)

最大的困难是那些“值”元素,其中一些字段包含简单的字符串,而在其他情况下则有一个元素数组

我尝试为元素“值”创建一个抽象类,然后再创建 2 个扩展抽象类的类。但这没有用

【问题讨论】:

  • 您是否可以控制 JSON 的来源?仅仅因为定义一个可能是 StringArray<Object> 类型的元素是非常糟糕的做法。您应该尝试获取具有良好架构的 JSON。
  • 你能分享你的 POJO 吗?
  • @McPringle,不幸的是我无法控制 JSON
  • @JoseA.Matarán,我最终使用了与 josejuan 提议的 POJO 相同的 POJO。小的区别是我使用 Map 而不是类 Outputs2ItemMeta

标签: java json jackson pojo


【解决方案1】:

最好的方法是创建一个自定义类型解析器:

static class Outputs {
    public String name;
    @JsonDeserialize(using = OutputsDeserializer.class)
    public OutputsValue value;
}

static abstract class OutputsValue {

}

@AllArgsConstructor
static class Outputs1 extends OutputsValue {
    public String value;
}

@AllArgsConstructor
static class Outputs2 extends OutputsValue {
    public List<Outputs2Item> value;
}

static class OutputsDeserializer extends JsonDeserializer<OutputsValue> {

    @Override
    public OutputsValue deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        ObjectCodec codec = jp.getCodec();
        JsonNode node = codec.readTree(jp);
        if (node.getNodeType().toString().equalsIgnoreCase("STRING"))
            return new Outputs1(codec.treeToValue(node, String.class));
        List<Outputs2Item> xs = new ArrayList<>();
        node.elements().forEachRemaining(e -> {
            try {
                xs.add(codec.treeToValue(e, Outputs2Item.class));
            } catch (JsonProcessingException ex) {
                ex.printStackTrace();
            }
        });
        return new Outputs2(xs);
    }
}

static class Outputs2Item {
    public List<Outputs2ItemMeta> metadata;
    public List<Object /* integer | string */ > data;
}

static class Outputs2ItemMeta {
    public String ID;
    public String NAME;
}

static class Pojo {
    public List<String> links;
    public int version;
    public String executionState;
    public List<Outputs> outputs;
}

运行

final Pojo o = new ObjectMapper().readValue(new File("/home/josejuan/tmp/z.json"), Pojo.class);

对象包含所有必需的值

【讨论】:

    【解决方案2】:

    您可以使用 Jackson 将 JSON 解析为 JsonNode 实例并自己创建 POJO,具体取决于 value 元素的类型:

    final var objectMapper = new ObjectMapper();
    final var jsonNode = objectMapper.readTree(json);
    

    然后就可以使用JsonNode提供的实例方法来检查值和类型,并创建对应的Java对象。

    【讨论】:

      猜你喜欢
      • 2013-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-02
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多