Spring Boot 反序列化具有RequestBody的发布请求时使用转换器

r1zhe5dt  于 2023-02-04  发布在  Spring
关注(0)|答案(1)|浏览(186)

我有一个Spring Boot 应用程序,它有一个Game模型,其中有一个抽象的骰子对象列表。有多个不同颜色的骰子扩展了这个骰子类,并由工厂创建。这个列表在进入数据库之前被转换为字符串,并在通过转换器类检索时转换回骰子对象。
然而,当我发出一个post请求并试图将requestbodyMap到game类时,它试图示例化骰子列表,这导致了以下错误:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `sagrada.model.dice.Die` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

是否可以使用某种类型的转换器或告诉它在Map到游戏之前将主体转换为正确的骰子对象?
游戏类:

@Entity
public class Game {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @OneToMany(mappedBy = "game")
    private List<GamePlayer> gamePlayers;

    @Convert(converter = GameStateConverter.class)
    private GameState state;

    @Convert(converter = GameDiceConverter.class)
    private List<Die> die;

    public List<Die> getDie() {
        return die;
    }

    public void setDie(List<Die> die) {
        this.die = die; 
    }
}

模具类别:

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

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

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

    public dieColor getColor() {
        return color;
    }

    public void setColor(dieColor color) {
        this.color = color;
    }
}

转换器类:

public class GameDiceConverter implements AttributeConverter<List<Die>, String> {
    @Override
    public String convertToDatabaseColumn(List<Die> dice) {
        StringBuilder diestring = new StringBuilder();

        for (Die die : dice) {
            String dieColor = die.getColor().toString();
            int dieValue = die.getValue();

            diestring.append(dieColor.charAt(0));
            diestring.append(dieValue);
        }

        return diestring.toString();
    }

    @Override
    public List<Die> convertToEntityAttribute(String s) {
        String[] dice = s.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;
    }
}

并请求:

@PostMapping("/")
    ResponseEntity<EntityModel<Game>> newGame(@RequestBody Game game) {
        game.setState(GameState.NEW);
        Game newGame = repository.save(game);

        return ResponseEntity
                .created(linkTo(methodOn(GameController.class).getGame(newGame.getId())).toUri())
                .body(assembler.toModel(newGame));
    }
yjghlzjz

yjghlzjz1#

错误“无法构造sagrada.model.dice.Die的示例(不存在创建器,如默认构造器):抽象类型要么需要Map到具体类型...”
指示“个人分发名单终止”;“无法启动
原因:“抽象类不能被示例化,但它们可以被子类化”另请参见:https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
建议变更:“public class Die”-删除抽象表单类(如果不必要)

相关问题