当我尝试反序列化对象列表时,杰克逊抛出错误映射异常

Posted

技术标签:

【中文标题】当我尝试反序列化对象列表时,杰克逊抛出错误映射异常【英文标题】:Jackson throws error mapping exception when I try to deserialize a list of objects 【发布时间】:2022-01-13 10:49:48 【问题描述】:

我尝试反序列化一个巨大的 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"
    
  ]

【问题讨论】:

【参考方案1】:

您应该简单地注释您的@JsonCreators 的参数。

@JsonCreator
public ObjectEntry(String objectKey) 
    this.objectKey = objectKey;

变成

@JsonCreator
public ObjectEntry(@JsonProperty(value = "objectKey", required = true) String objectKey) 
    this.objectKey = objectKey;

其他构造函数也是如此。

解释:

序列化:您有一个带有字段的实例,您使用@JsonProperty("name")(或带有@JsonValue 的getter)注释一个字段,这允许Jackson 通过反射从您的实例构建一个字符串json。 反序列化:遵循相同的逻辑,当您使用@JsonCreator 注释构造函数时,您是在告诉杰克逊这是他们应该使用的构造函数,用于从他们拥有的 Json 字符串构建您的对象。但是,要么你给他们一个空的构造函数(然后通过反射,他们稍后会设置每个字段),或者你必须告诉他们必须在每个构造函数参数中使用 Json 字符串的哪个字段。

【讨论】:

以上是关于当我尝试反序列化对象列表时,杰克逊抛出错误映射异常的主要内容,如果未能解决你的问题,请参考以下文章

杰克逊在失踪财产的反序列化期间抛出NPE

序列化 Hibernate 对象时抛出奇怪的 Jackson 异常

Spring框架中的Jackson反序列化错误处理

杰克逊不能反序列化空数组

JSON杰克逊序列化反序列化列表列表

GWT:枚举列表抛出“无法反序列化响应”