gpt4 book ai didi

java - 使用 Jackson 将 JSON 反序列化为异构元素列表

转载 作者:行者123 更新时间:2023-11-30 06:12:50 26 4
gpt4 key购买 nike

在我的 JSON 中,我有一个包含以下内容的元素:

{
...
"locations": [
[
{
"location_type": "permanent",
"position": "at",
"accuracy": "exact"
},
"and",
{
"location_type": "permanent",
"position": "in",
"accuracy": "exact"
}
],
"or",
{
"location_type": "temporary",
"position": "at",
"accuracy": "exact"
}
],
...
}

如图所示,locations的元素可以是:

  • 地点
  • 逻辑运算符
  • 位置列表(允许复杂的位置)

我收到“无法从 START_ARRAY token 中反序列化 com.example.processor.transformation.json.Location 的实例”。

如何使用 Jackson 将其消费到数据结构中?

到目前为止我尝试过的:

  1. 提供 Location(String logicalOperator)构造函数有助于平面列表的情况。 (我基本上将运算符转换为特殊值 Location 。)
  2. 添加 Location(List<Location> subLocations)Location(Location[] subLocations)构造函数对于这种情况没有帮助。

注意:我无法控制 JSON 格式,因此无法以对 Jackson 更友好的方式对其进行编码。

最佳答案

为此,您将需要一个自定义反序列化器。您不能只添加构造函数。

这是一个类 Foo 的独立示例,它可以由其自己的属性 "foo": "someString" 或某些逻辑运算符 表示>"and""or" 等作为 String 文字,旨在表示 Foo 实例,其 foo 属性将是该文字的值。

这可能完全适合您的情况,也可能不完全适合您的情况,但您可以进行调整。

换句话说:

  • {"foo": "a"} --> new Foo("a")
  • “或” --> new Foo(“或”)

示例

// given...

@JsonDeserialize(using=MyDeserializer.class)
class Foo {
String foo;
public void setFoo(String s) {
foo = s;
}
public String getFoo() {
return foo;
}
public Foo(String s) {
setFoo(s);
}
}

//和自定义反序列化器...

class MyDeserializer extends JsonDeserializer<Foo> {

@Override
public Foo deserialize(JsonParser jp, DeserializationContext ct)
throws IOException, JsonProcessingException {
ObjectCodec oc = jp.getCodec();
JsonNode node = oc.readTree(jp);
// this JSON object has a "foo" property, de-serialize
// injecting its value in Foo's constructor
if (node.has("foo")) {
return new Foo(node.get("foo").asText());
}
// other case, assuming literal (e.g. "and", "or", etc.)
// inject actual node as String value into Foo's constructor
else {
return new Foo(node.asText());
}
}

}

// here's a quick example

String json = "[{\"foo\": \"a\"}, \"or\", {\"foo\": \"b\"}]";
ObjectMapper om = new ObjectMapper();
List<Foo> list = om.readValue(json, new TypeReference<List<Foo>>(){});
list.forEach(f -> System.out.println(f.foo));

输出

a
or
b

为了清晰起见,请注意

这是一个非常简单的示例。在您的情况下,您可能需要一个 Location POJO 与 LogicalOperator POJO(或类似的东西)混合的多态集合,共享一个公共(public)标记接口(interface)。然后,您可以根据 JSON 节点是否包含内容(即位置)或 JSON 节点是否是其内容(例如逻辑运算符)来决定要反序列化的对象。

关于java - 使用 Jackson 将 JSON 反序列化为异构元素列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49853558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com