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

Jackson转换含枚举属性对象为Map时枚举值变为String类型问题

问题原因
  • 你添加的@Enumerated(EnumType.STRING)是JPA持久层规范的注解,仅对Hibernate这类ORM框架的数据库存储逻辑生效,Jackson完全不识别这个注解,不会对ObjectMapper的类型转换行为产生任何影响。
  • 核心问题来自Jackson的默认转换逻辑:convertValue的执行流程等价于先将源对象序列化为JSON中间结构,再把中间结果反序列化为你传入的目标类型。你传入的目标类型是无泛型声明的原始Map.class,Jackson会将Map的value类型识别为通用Object,而JSON本身没有枚举类型,Jackson默认会把枚举值序列化为枚举名称字符串存入中间结构,最终反序列化得到的Map里,color字段自然是String类型——就算你删掉@Enumerated注解,默认转换结果依然是String。
解决方案

根据实际业务场景选择对应方案即可:

方案1:全局配置保留枚举实例

如果所有枚举类型在转Map时都需要保留原始枚举对象,给ObjectMapper注册自定义枚举序列化器即可:

// 自定义枚举序列化器,直接保留原始枚举引用
class EnumPreserveSerializer extends StdSerializer<Enum> {
    protected EnumPreserveSerializer() {
        super(Enum.class);
    }

    @Override
    public void serialize(Enum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeEmbeddedObject(value);
    }
}

// 初始化MAPPER时注册模块
ObjectMapper MAPPER = new ObjectMapper();
SimpleModule enumModule = new SimpleModule();
enumModule.addSerializer(Enum.class, new EnumPreserveSerializer());
MAPPER.registerModule(enumModule);

配置完成后再调用convertValue,Map里的color字段就会保留原始的Color枚举类型。注意这个配置不要和普通JSON序列化共用ObjectMapper实例,JSON本身不支持枚举类型,会导致序列化报错,建议给转Map场景单独维护专用的Mapper实例。

方案2:单字段指定保留枚举

如果只有个别枚举字段需要保留原类型,不需要修改全局Mapper配置,给对应字段添加Jackson的序列化注解即可:

public class Car{
    ...
    @Enumerated(EnumType.STRING) // 该注解仅给JPA持久层使用,和Jackson逻辑无关
    @JsonSerialize(using = EnumPreserveSerializer.class)
    private Color color;
    ...
}

注解里引用的序列化器直接复用方案1中定义的EnumPreserveSerializer即可。

方案3:手动转换枚举值

如果只是需要读取枚举值,不需要Map内存储枚举实例,不需要修改Mapper配置,取值时手动转换即可:

Map<String, Object> toMap = MAPPER.convertValue(t, Map.class);
Color carColor = Color.valueOf((String) toMap.get("color"));

这个方案改造成本最低,适合转换后仅需要读取枚举值的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.19 16:15:45