我如何使用 Jackson 来解析带有可变对象名称的 JSON?
How can I use Jackson to parse JSON with variable object names?
Google 的 cAdvisor API 给出如下 JSON 输出:
{
/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope: {},
/system.slice/docker-747f797d19931b4ef33cda0c519f935b592a0b828d16b8cafc350568ab2c1d28.scope: {},
/system.slice/docker-bf947bfabf61cd5168bd599162cf5f5c2ea2350eece1ded018faebf598f7ee5b.scope: {},
/system.slice/docker-e8e02d508400438603151dd462ef036d59fada8239f66be8e64813880b59a77d.scope: {
name: "/system.slice/docker-e8e02d508400438603151dd462ef036d59fada8239f66be8e64813880b59a77d.scope",
aliases: [...],
namespace: "docker",
spec: {...},
stats: [...]
}
}
我将其描述为 4 个具有 variable/anonymous 名称的相同类型 JSON 对象,保存在一个匿名对象中。
我的第一个想法就是做类似 mapper.readValue(response, Containers.class)
的事情,其中:
public class Containers extends BaseJsonObject {
@JsonProperty
public List<Container> containerList;
}
和
public class Container extends BaseJsonObject {
@JsonProperty
private String name;
@JsonProperty
public String[] aliases;
@JsonProperty
private String namespace;
@JsonProperty
private String spec;
@JsonProperty
public Stats[] stats;
}
但是我能想到的所有变体都会产生相同的结果:com.xyz.Containers@45c7e403[containerList=<null>]
或 com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope" (class com.xyz.Containers), not marked as ignorable (one known property: "containerList"])
at [Source: java.io.StringReader@3d285d7e; line: 1, column: 97] (through reference chain: com.xyz.Containers["/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope"])
与 ACCEPT_SINGLE_VALUE_AS_ARRAY = false
的一些排列。
我试过:
mapper.readValue(response, Container[].class)
mapper.readValue(response, Containers.class)
mapper.readValues(jsonParser, Container.class)
以及以下配置:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
我如何解析 JSON 名称为 variable/anonymous 且保存在非数组中的对象?这个叫什么?
可以如下使用the @JsonAnySetter annotation,将变量名对象放入Map<String, Container>
的map中。
这是一个例子:
public class JacksonVariableNames {
static final String JSON = "{\n"
+ " \"a\": {\n"
+ " \"value\": \"1\"\n"
+ " },\n"
+ " \"b\": {\n"
+ " \"value\": \"2\"\n"
+ " },\n"
+ " \"c\": {\n"
+ " \"value\": \"3\"\n"
+ " }\n"
+ "}";
static class Value {
private final String value;
@JsonCreator
Value(@JsonProperty("value") final String value) {this.value = value;}
@Override
public String toString() {
return "Value{" +
"value='" + value + '\'' +
'}';
}
}
static class Values {
private final Map<String, Value> values = new HashMap<>();
@JsonAnySetter
public void setValue(final String property, final Value value) {
values.put(property, value);
}
@Override
public String toString() {
return "Values{" +
"values=" + values +
'}';
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(JSON, Values.class));
}
}
输出:
Values{values={a=Value{value='1'}, b=Value{value='2'}, c=Value{value='3'}}}
Google 的 cAdvisor API 给出如下 JSON 输出:
{
/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope: {},
/system.slice/docker-747f797d19931b4ef33cda0c519f935b592a0b828d16b8cafc350568ab2c1d28.scope: {},
/system.slice/docker-bf947bfabf61cd5168bd599162cf5f5c2ea2350eece1ded018faebf598f7ee5b.scope: {},
/system.slice/docker-e8e02d508400438603151dd462ef036d59fada8239f66be8e64813880b59a77d.scope: {
name: "/system.slice/docker-e8e02d508400438603151dd462ef036d59fada8239f66be8e64813880b59a77d.scope",
aliases: [...],
namespace: "docker",
spec: {...},
stats: [...]
}
}
我将其描述为 4 个具有 variable/anonymous 名称的相同类型 JSON 对象,保存在一个匿名对象中。
我的第一个想法就是做类似 mapper.readValue(response, Containers.class)
的事情,其中:
public class Containers extends BaseJsonObject {
@JsonProperty
public List<Container> containerList;
}
和
public class Container extends BaseJsonObject {
@JsonProperty
private String name;
@JsonProperty
public String[] aliases;
@JsonProperty
private String namespace;
@JsonProperty
private String spec;
@JsonProperty
public Stats[] stats;
}
但是我能想到的所有变体都会产生相同的结果:com.xyz.Containers@45c7e403[containerList=<null>]
或 com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope" (class com.xyz.Containers), not marked as ignorable (one known property: "containerList"])
at [Source: java.io.StringReader@3d285d7e; line: 1, column: 97] (through reference chain: com.xyz.Containers["/system.slice/docker-13b18253fa70d837e9707a1c28e45a3573e82751f964b66d7c4cbc2256abc266.scope"])
与 ACCEPT_SINGLE_VALUE_AS_ARRAY = false
的一些排列。
我试过:
mapper.readValue(response, Container[].class)
mapper.readValue(response, Containers.class)
mapper.readValues(jsonParser, Container.class)
以及以下配置:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
我如何解析 JSON 名称为 variable/anonymous 且保存在非数组中的对象?这个叫什么?
可以如下使用the @JsonAnySetter annotation,将变量名对象放入Map<String, Container>
的map中。
这是一个例子:
public class JacksonVariableNames {
static final String JSON = "{\n"
+ " \"a\": {\n"
+ " \"value\": \"1\"\n"
+ " },\n"
+ " \"b\": {\n"
+ " \"value\": \"2\"\n"
+ " },\n"
+ " \"c\": {\n"
+ " \"value\": \"3\"\n"
+ " }\n"
+ "}";
static class Value {
private final String value;
@JsonCreator
Value(@JsonProperty("value") final String value) {this.value = value;}
@Override
public String toString() {
return "Value{" +
"value='" + value + '\'' +
'}';
}
}
static class Values {
private final Map<String, Value> values = new HashMap<>();
@JsonAnySetter
public void setValue(final String property, final Value value) {
values.put(property, value);
}
@Override
public String toString() {
return "Values{" +
"values=" + values +
'}';
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue(JSON, Values.class));
}
}
输出:
Values{values={a=Value{value='1'}, b=Value{value='2'}, c=Value{value='3'}}}