Spring RestController请求体枚举反序列化问题咨询
解决Spring MVC枚举反序列化与AngularJS调用的匹配问题
我之前碰到过类似的问题,你这个情况核心是Spring默认的枚举反序列化逻辑和你的枚举定义、前端传值不匹配,导致接口没法正确解析AngularJS传过来的参数。下面给你几个实用的解决办法:
方法1:自定义枚举转换器让Spring识别你的自定义文本值
你可以写一个转换器,告诉Spring怎么把前端传的字符串映射到DeckSuit枚举实例。
第一步:编写转换器类
import org.springframework.core.convert.converter.Converter; import org.springframework.stereotype.Component; @Component public class DeckSuitConverter implements Converter<String, DeckSuit> { @Override public DeckSuit convert(String source) { // 遍历所有枚举值,匹配传入的自定义文本 for (DeckSuit suit : DeckSuit.values()) { if (suit.toString().equals(source)) { return suit; } } // 匹配失败可以抛异常或者返回默认值,根据你的业务需求来 throw new IllegalArgumentException("无效的DeckSuit值: " + source); } }
第二步:让Spring加载这个转换器
如果是Spring Boot项目,只要给转换器加上@Component注解,Spring会自动注册它。要是传统Spring MVC项目,就得在配置类里手动注册:
import org.springframework.context.annotation.Configuration; import org.springframework.format.FormatterRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { registry.addConverter(new DeckSuitConverter()); } }
配置完之后,AngularJS传SpanishSuit或者FrenchSuit,Spring就能正确转成对应的枚举实例了。
方法2:调整前端传值,用枚举名称而非自定义文本
要是不想改后端代码,也可以直接改AngularJS的请求参数,传枚举的原始名称(也就是SPANISH_SUIT或者FRENCH_SUIT),这样Spring默认的反序列化逻辑就能直接识别。
比如你的Angular请求代码可以改成这样:
// 把原来的"SpanishSuit"改成枚举名称"SPANISH_SUIT" $http.post('/your-api-path', 'SPANISH_SUIT') .then(function(res) { // 处理成功响应 }) .catch(function(err) { // 处理错误 });
方法3:用Jackson注解统一枚举的序列化/反序列化规则
如果你的项目用Jackson处理JSON(Spring Boot默认就是Jackson),可以给枚举加两个注解,直接指定用自定义的text字段来做序列化和反序列化。
修改你的枚举类:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; public enum DeckSuit { SPANISH_SUIT("SpanishSuit"), FRENCH_SUIT("FrenchSuit"); private final String text; DeckSuit(final String text) { this.text = text; } // 告诉Jackson序列化枚举时输出text值 @JsonValue @Override public String toString() { return text; } // 告诉Jackson反序列化时根据text值匹配枚举 @JsonCreator public static DeckSuit fromText(String text) { for (DeckSuit suit : DeckSuit.values()) { // 这里可以加equalsIgnoreCase,兼容大小写错误的情况 if (suit.text.equals(text)) { return suit; } } throw new IllegalArgumentException("无效的DeckSuit文本: " + text); } }
加了这两个注解之后,Jackson会自动用text字段来处理前后端的枚举交互:前端传SpanishSuit后端能解析成SPANISH_SUIT,后端返回枚举时也会输出SpanishSuit,前后端的格式就统一了。
内容的提问来源于stack exchange,提问作者MABC
相关产品推荐
相关产品推荐

