在我的 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 将其消费到数据结构中?
到目前为止我尝试过的:
- 提供
Location(String logicalOperator)
构造函数有助于平面列表的情况。 (我基本上将运算符转换为特殊值Location
。) - 添加
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/