当我尝试反序列化对象列表时,Jackson 抛出错误映射异常
Jackson throws error mapping exception when I try to deserialize a list of objects
我尝试反序列化一个巨大的 API 负载。此有效负载包含的字段比我需要的多得多,因此我正在使用 @JsonIgnoreProperties(ignoreUnknown = true)
。但是在某些时候反序列化失败并显示错误消息:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of FIELD_NAME token
at [Source: {
"objectEntries": [
{
"objectKey": "KDS-4300"
},
{
"objectKey": "KDS-4327"
}
]
}; line: 2, column: 3]
我找到了建议使用
的那个案例的解决方案
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
我试过了。但这没有帮助。我的结果数据也不是单值数组。它实际上包含两个值 - 因此该解决方案无论如何都不会加起来。
这是我的 类 反序列化的目标。
@JsonIgnoreProperties(ignoreUnknown = true)
public class InsightQueryResult {
@JsonProperty("objectEntries")
private List<ObjectEntry> objectEntries;
@JsonCreator
public InsightQueryResult(List<ObjectEntry> objectEntries) {
this.objectEntries = objectEntries;
}
public List<ObjectEntry> getObjectEntries() {
return objectEntries;
}
// equals, hashCode and toString
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class ObjectEntry {
@JsonProperty("objectKey")
private String objectKey;
@JsonCreator
public ObjectEntry(String objectKey) {
this.objectKey = objectKey;
}
public String getObjectKey() {
return objectKey;
}
// equals, hashCode and toString
}
这是我测试的单元测试:
@Test
public void shouldMapQueryResultToResultObject() throws IOException {
final Resource expectedQueryResult= new ClassPathResource("testQueryPayload.json");
final String expectedQueryResultData = new String(
Files.readAllBytes(expectedQueryResult.getFile().toPath())).trim();
final List<ObjectEntry> objectEntries = Arrays.asList(new ObjectEntry("KDS-4300"), new ObjectEntry("KD-4327"));
final InsightQueryResult expectedQueryResult = new InsightQueryResult(objectEntries);
final InsightQueryResult result = objectMapper.readValue(expectedQueryResultData, InsightQueryResult.class);
assertThat(result).isEqualTo(expectedQueryResult);
}
这是我要反序列化的负载
// testQueryPayload.json
{
"objectEntries": [
{
"objectKey": "KDS-4300"
},
{
"objectKey": "KDS-4327"
}
]
}
您应该简单地注释您的 @JsonCreator
s 的参数。
@JsonCreator
public ObjectEntry(String objectKey) {
this.objectKey = objectKey;
}
变成
@JsonCreator
public ObjectEntry(@JsonProperty(value = "objectKey", required = true) String objectKey) {
this.objectKey = objectKey;
}
另一个构造函数也是如此。
解释:
- 序列化:你有一个带有字段的实例,你用
@JsonProperty("name")
注释一个字段(或者 getter 带有 @JsonValue
),这允许 Jackson 构建一个字符串 json 通过反射从您的实例中获取。
- 反序列化:遵循相同的逻辑,当您使用
@JsonCreator
注释构造函数时,您是在告诉 Jackson 这是他们应该用来从他们拥有的 Json 字符串构建对象的构造函数。然而,要么你给他们一个空的构造函数(然后通过反射他们稍后会设置每个字段),要么你必须告诉他们他们必须在每个构造函数参数中使用 Json 字符串的哪个字段。
我尝试反序列化一个巨大的 API 负载。此有效负载包含的字段比我需要的多得多,因此我正在使用 @JsonIgnoreProperties(ignoreUnknown = true)
。但是在某些时候反序列化失败并显示错误消息:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of FIELD_NAME token
at [Source: {
"objectEntries": [
{
"objectKey": "KDS-4300"
},
{
"objectKey": "KDS-4327"
}
]
}; line: 2, column: 3]
我找到了建议使用
的那个案例的解决方案objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
我试过了。但这没有帮助。我的结果数据也不是单值数组。它实际上包含两个值 - 因此该解决方案无论如何都不会加起来。
这是我的 类 反序列化的目标。
@JsonIgnoreProperties(ignoreUnknown = true)
public class InsightQueryResult {
@JsonProperty("objectEntries")
private List<ObjectEntry> objectEntries;
@JsonCreator
public InsightQueryResult(List<ObjectEntry> objectEntries) {
this.objectEntries = objectEntries;
}
public List<ObjectEntry> getObjectEntries() {
return objectEntries;
}
// equals, hashCode and toString
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class ObjectEntry {
@JsonProperty("objectKey")
private String objectKey;
@JsonCreator
public ObjectEntry(String objectKey) {
this.objectKey = objectKey;
}
public String getObjectKey() {
return objectKey;
}
// equals, hashCode and toString
}
这是我测试的单元测试:
@Test
public void shouldMapQueryResultToResultObject() throws IOException {
final Resource expectedQueryResult= new ClassPathResource("testQueryPayload.json");
final String expectedQueryResultData = new String(
Files.readAllBytes(expectedQueryResult.getFile().toPath())).trim();
final List<ObjectEntry> objectEntries = Arrays.asList(new ObjectEntry("KDS-4300"), new ObjectEntry("KD-4327"));
final InsightQueryResult expectedQueryResult = new InsightQueryResult(objectEntries);
final InsightQueryResult result = objectMapper.readValue(expectedQueryResultData, InsightQueryResult.class);
assertThat(result).isEqualTo(expectedQueryResult);
}
这是我要反序列化的负载
// testQueryPayload.json
{
"objectEntries": [
{
"objectKey": "KDS-4300"
},
{
"objectKey": "KDS-4327"
}
]
}
您应该简单地注释您的 @JsonCreator
s 的参数。
@JsonCreator
public ObjectEntry(String objectKey) {
this.objectKey = objectKey;
}
变成
@JsonCreator
public ObjectEntry(@JsonProperty(value = "objectKey", required = true) String objectKey) {
this.objectKey = objectKey;
}
另一个构造函数也是如此。
解释:
- 序列化:你有一个带有字段的实例,你用
@JsonProperty("name")
注释一个字段(或者 getter 带有@JsonValue
),这允许 Jackson 构建一个字符串 json 通过反射从您的实例中获取。 - 反序列化:遵循相同的逻辑,当您使用
@JsonCreator
注释构造函数时,您是在告诉 Jackson 这是他们应该用来从他们拥有的 Json 字符串构建对象的构造函数。然而,要么你给他们一个空的构造函数(然后通过反射他们稍后会设置每个字段),要么你必须告诉他们他们必须在每个构造函数参数中使用 Json 字符串的哪个字段。