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

Play Framework中如何通过枚举字段将请求参数转为Enum类型

解决Play Framework枚举自定义字段绑定问题

Play Framework默认会使用枚举的name()方法(即枚举常量名,比如BANANA)来进行参数绑定,所以你传入"banana"时无法匹配,需要通过以下两种方式解决,分别覆盖JSON请求体绑定和表单参数绑定场景:

1. 处理JSON请求体绑定(推荐,适配你的POST JSON场景)

直接在Fruits枚举中添加Jackson注解,指定序列化/反序列化规则:

修改后的Fruits枚举

@AllArgsConstructor
public enum Fruits {
    APPLE("apple"),
    BANANA("banana"),
    KIWI("kiwi"),
    DRAGON_FRUIT("dragonFruit");

    private final String fruitName;

    private static final Map<String, Fruits> fruitsByFruitName; 

    static {
        fruitsByFruitName = new HashMap<>(); 
        fruitsByFruitName.put("apple", APPLE);
        fruitsByFruitName.put("banana", BANANA);
        fruitsByFruitName.put("kiwi", KIWI);
        fruitsByFruitName.put("dragonFruit", DRAGON_FRUIT);
    }

    // 标记为Jackson反序列化入口方法
    @JsonCreator
    public static Fruits fromFruitName(String fruitName) throws InvalidEnumException {
        // 修正原代码逻辑错误:contains()改为containsKey(),判断键是否存在
        if(fruitsByFruitName.containsKey(fruitName)) {
            return fruitsByFruitName.get(fruitName);
        } else {
            throw new InvalidEnumException("无效的水果名称: " + fruitName);
        }
    } 

    // 指定枚举序列化为JSON时输出的字段值
    @JsonValue
    public String getFruitName() {
        return fruitName;
    }
}

添加@JsonCreator后,Jackson会调用fromFruitName方法将JSON字符串转换为枚举实例;@JsonValue则控制枚举序列化为JSON时输出的内容。

2. 处理表单参数绑定(适配表单提交场景)

如果你的请求是表单格式(而非JSON),需要自定义Formatter并完成注册:

步骤1:创建自定义Formatter

import play.data.format.Formatter;
import play.data.validation.ValidationError;

import java.util.Locale;
import java.util.Optional;

public class FruitsFormatter implements Formatter<Fruits> {

    @Override
    public Optional<Fruits> parse(String input, Locale locale) {
        try {
            return Optional.of(Fruits.fromFruitName(input));
        } catch (InvalidEnumException e) {
            return Optional.empty();
        }
    }

    @Override
    public String print(Fruits fruits, Locale locale) {
        return fruits.getFruitName();
    }
}

步骤2:注册Formatter

有两种注册方式可选:

  • 全局注册:在conf/application.conf中添加配置:
    play.data.formatters.java=FruitsFormatter
    
  • 局部注册:在模型字段上添加注解:
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class MyReqBody {
        @Formats.Format(FruitsFormatter.class)
        private Fruits favFruit;
    }
    

关键注意事项

  • 修正了原代码中fruitsByFruitName.contains(fruitName)的逻辑错误:contains()是判断集合是否包含指定值,这里需要用containsKey()判断Map中是否存在指定键。
  • 如果同时存在JSON和表单请求场景,需要同时配置上述两种方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 21:54:17