Spring Boot Enum多@JsonValue注解报错,需实现多格式JSON反序列化
解决方案:用
@JsonCreator处理多格式输入,避免@JsonValue冲突 核心思路
@JsonValue注解只能标记一个方法(用于指定枚举序列化时的输出格式),不能同时标在两个方法上。要实现数字、大小写不敏感月份名称、甚至混合格式的输入支持,应该用@JsonCreator自定义反序列化逻辑,同时保留单个@JsonValue控制序列化输出。
完整代码示例
public enum MonthEnum { JANUARY(1, "January"), FEBRUARY(2, "February"), MARCH(3, "March"), APRIL(4, "April"), MAY(5, "May"), JUNE(6, "June"), JULY(7, "July"), AUGUST(8, "August"), SEPTEMBER(9, "September"), OCTOBER(10, "October"), NOVEMBER(11, "November"), DECEMBER(12, "December"); private final int code; private final String name; private final String lowerName; MonthEnum(int code, String name) { this.code = code; this.name = name; this.lowerName = name.toLowerCase(); } public int getCode() { return code; } public String getName() { return name; } public String getLowerName() { return lowerName; } // 自定义反序列化逻辑,覆盖所有输入格式 @JsonCreator public static MonthEnum fromValue(Object input) { if (input == null) { throw new IllegalArgumentException("月份参数不能为空"); } // 处理数字输入(1-12) if (input instanceof Integer) { int targetCode = (Integer) input; for (MonthEnum month : values()) { if (month.code == targetCode) { return month; } } } // 处理字符串输入(纯名称、混合格式) if (input instanceof String) { String rawValue = ((String) input).trim(); String lowerValue = rawValue.toLowerCase(); // 先尝试转数字匹配code try { int code = Integer.parseInt(lowerValue); return fromValue(code); } catch (NumberFormatException e) { // 匹配大小写不敏感的月份名称 for (MonthEnum month : values()) { if (month.lowerName.equals(lowerValue)) { return month; } } // 处理混合格式(如"1-January"、"february-2") String[] parts = lowerValue.split("-"); if (parts.length == 2) { // 尝试code在前、名称在后的格式 tryMatchMixedFormat(parts[0].trim(), parts[1].trim()); // 尝试名称在前、code在后的格式 tryMatchMixedFormat(parts[1].trim(), parts[0].trim()); } } } // 非法参数提示,替换成你已有的错误逻辑 throw new IllegalArgumentException( String.format("无效的月份参数:%s。支持格式:1-12的数字、大小写不敏感的月份名称(如January/january)、或数字+名称的混合格式(如1-January)", input) ); } // 辅助方法:验证混合格式的code和name是否匹配 private static MonthEnum tryMatchMixedFormat(String codeStr, String nameStr) { try { int code = Integer.parseInt(codeStr); MonthEnum month = fromValue(code); if (month.lowerName.equals(nameStr)) { return month; } } catch (NumberFormatException | IllegalArgumentException ignored) { // 匹配失败,继续抛出最终异常 } return null; } // 可选:指定序列化输出格式(二选一,或自定义序列化器输出多种) @JsonValue public int serializeAsCode() { return code; } // 如果需要序列化输出名称,替换上面的方法: // @JsonValue // public String serializeAsName() { // return name; // } }
关键说明
- 移除多
@JsonValue注解:只保留一个@JsonValue用于控制序列化时的输出格式(数字或名称,根据业务需求选择),解决注解冲突问题。 @JsonCreator处理多格式输入:- 优先处理数字类型输入;
- 字符串类型先尝试转数字,失败后匹配大小写不敏感的月份名称;
- 额外支持数字+名称的混合格式验证;
- 不匹配时抛出你已定义的非法参数提示。
- 扩展性:如果需要支持更多输入格式(如缩写"Jan"),只需在字符串匹配逻辑中添加对应判断即可。
内容的提问来源于stack exchange,提问作者Gianni Spear
相关产品推荐
相关产品推荐

