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>:
- 先写反序列化器类:
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()); } }
- 然后在
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
相关产品推荐
相关产品推荐

