You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSON二维数组反序列化为自定义对象列表报错求助

解决Jackson反序列化二维数组为自定义对象列表的问题

首先我得指出你代码里的几个明显笔误,这些先修正了才能继续:

  • Attempt类的@Builder注解里builderClassName = "Attempt Builder"有空格,应该改成"AttemptBuilder"(或者直接去掉这个参数,默认生成的Builder类名就是AttemptBuilder);
  • @JsonDeserialize(builder = Attempt .Attempt Builder.class)里的空格是语法错误,正确写法是Attempt.AttemptBuilder.class。

接下来说说你遇到的核心问题:你的JSON里rows对应的是二维数组(比如[[4,4,5], [3,3,3]]),但Jackson默认会把每个子数组当成要映射到Attempt对象的键值对结构,可Attempt是一个包含attemptList字段的对象,不是数组,所以Jackson找不到对应的属性映射关系,就抛出了Cannot deserialize instance of Attempt$AttemptBuilder out of START_ARRAY错误。

这里有两种简洁的解决办法:


方法一:给Attempt添加@JsonCreator构造函数

让Jackson明确知道如何用一个数组(转成List<Integer>)来创建Attempt对象,修改后的Attempt类如下:

@Getter
@Builder(builderClassName = "AttemptBuilder", toBuilder = true)
@JsonDeserialize(builder = Attempt.AttemptBuilder.class)
class Attempt {
    List<Integer> attemptList;

    // 用@JsonCreator标记,Jackson会把JSON中的子数组转为List<Integer>传入
    @JsonCreator
    public Attempt(List<Integer> attemptList) {
        this.attemptList = attemptList;
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class AttemptBuilder { }
}

这样Jackson在反序列化时,会自动把每个子数组转成List<Integer>,然后通过这个构造函数生成Attempt对象,最终组装成List<Attempt>。


方法二:给Action的attempts字段添加自定义反序列化器

如果不想修改Attempt类的构造逻辑,可以写一个自定义的反序列化器,把List<List<Integer>>手动转成List<Attempt>:

  1. 先写反序列化器类:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

public class AttemptListDeserializer extends JsonDeserializer<List<Attempt>> {
    @Override
    public List<Attempt> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        // 先把JSON数组读成二维List
        List<List<Integer>> rawRows = p.readValueAs(new com.fasterxml.jackson.core.type.TypeReference<List<List<Integer>>>() {});
        // 转成Attempt列表
        return rawRows.stream()
                .map(row -> Attempt.builder().attemptList(row).build())
                .collect(Collectors.toList());
    }
}
  1. 然后在Action的attempts字段上标记使用这个反序列化器:
@Getter
@Builder(builderClassName = "ActionBuilder", toBuilder = true)
@JsonDeserialize(builder = Action.ActionBuilder.class)
class Action{
    @JsonDeserialize(using = AttemptListDeserializer.class)
    List<Attempt> attempts;

    @JsonPOJOBuilder(withPrefix = "")
    public static class ActionBuilder { }
}

两种方法都能解决你的问题,第一种更简洁,第二种更灵活(如果后续需要更复杂的转换逻辑)。

内容的提问来源于stack exchange,提问作者Trusk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:27:48