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

Spring Boot POST请求中抽象Die列表属性的反序列化异常解决咨询

问题原因

你遇到的异常是因为Jackson处理HTTP请求体的反序列化时,无法实例化抽象类Die——既没有无参构造器,Jackson也不知道该映射到哪个具体的骰子子类。注意:JPA的@Convert注解只负责实体与数据库字段的转换,和JSON的序列化/反序列化完全无关,所以得针对Jackson单独配置。


解决方案

方案一:用Jackson类型注解自动识别子类

在抽象类Die上添加Jackson的类型注解,让它能根据JSON中的字段自动匹配具体子类:

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(
    use = JsonTypeInfo.Id.NAME,
    include = JsonTypeInfo.As.PROPERTY,
    property = "color" // 对应请求体中每个Die对象的color字段
)
@JsonSubTypes({
    @JsonSubTypes.Type(value = BlueDie.class, name = "BLUE"),
    @JsonSubTypes.Type(value = GreenDie.class, name = "GREEN"),
    @JsonSubTypes.Type(value = PurpleDie.class, name = "PURPLE"),
    @JsonSubTypes.Type(value = RedDie.class, name = "RED"),
    @JsonSubTypes.Type(value = YellowDie.class, name = "YELLOW")
})
public abstract class Die {
    private int value;
    private dieColor color;

    // 新增protected无参构造器,Jackson反序列化需要
    protected Die() {}

    public Die(int value) {
        this.value = value;
    }

    // 原有getter/setter保留
}

说明:只要请求体中的每个Die对象包含color字段(值和枚举dieColor的name一致),Jackson就会自动实例化对应的子类。

方案二:自定义Jackson反序列化器(适配字符串格式)

如果请求体中的骰子是用类似数据库存储的字符串格式(比如"R3B5"),可以写一个自定义反序列化器处理List<Die>:

  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.ArrayList;
import java.util.List;

public class DieListDeserializer extends JsonDeserializer<List<Die>> {
    @Override
    public List<Die> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String diceStr = p.getText();
        String[] dice = diceStr.split("(?<=\\G.{2})");
        List<Die> result = new ArrayList<>();

        for (String die : dice) {
            switch (die.charAt(0)) {
                case 'B' -> result.add(new BlueDie(die.charAt(1) - '0'));
                case 'G' -> result.add(new GreenDie(die.charAt(1) - '0'));
                case 'P' -> result.add(new PurpleDie(die.charAt(1) - '0'));
                case 'R' -> result.add(new RedDie(die.charAt(1) - '0'));
                case 'Y' -> result.add(new YellowDie(die.charAt(1) - '0'));
            }
        }
        return result;
    }
}
  1. 在Game类的die字段上绑定反序列化器:
@Entity
public class Game {
    // 其他字段保留

    @Convert(converter = GameDiceConverter.class)
    @JsonDeserialize(using = DieListDeserializer.class) // 新增该注解
    private List<Die> die;

    // 原有getter/setter保留
}

这样请求体中的die字段如果是字符串格式,Jackson会自动转成List<Die>。

方案三:配合@JsonCreator优化构造器

如果请求体中的每个Die是对象格式(比如{"color":"RED", "value":3}),可以给Die的构造器添加@JsonCreator注解,让Jackson直接用带参构造器实例化:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public abstract class Die {
    private int value;
    private dieColor color;

    @JsonCreator
    public Die(@JsonProperty("value") int value, @JsonProperty("color") dieColor color) {
        this.value = value;
        this.color = color;
    }

    // 原有getter/setter保留
}

说明:该方案配合方案一的类型注解使用效果最佳,能同时解决子类识别和构造器问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:10:35