如何用Jackson @JsonSerialize实现通用枚举转Integer序列化?
实现通用的枚举序列化器(Integer转枚举)
你遇到的问题根源是Java泛型擦除特性——编译后泛型参数会被抹除,Jackson无法在运行时获取泛型传递的枚举类型,因此直接用泛型的方式不可行。下面是一套通用解决方案,只需要一个序列化器就能适配所有符合规范的枚举类:
步骤1:定义通用枚举接口
让所有需要转换的枚举类实现这个接口,统一code的获取逻辑:
public interface CodeEnum { Integer getCode(); }
步骤2:改造现有枚举类
让你的StatusEnum(以及其他需要转换的枚举类)实现上述接口:
public enum StatusEnum implements CodeEnum { ON(1), OFF(0); private final Integer code; StatusEnum(Integer code) { this.code = code; } @Override public Integer getCode() { return code; } }
步骤3:自定义注解传递枚举类型
通过自定义注解,明确指定当前字段对应的目标枚举类:
import java.lang.annotation.*; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface EnumSerialize { // 指定要转换的枚举类 Class<? extends Enum<? extends CodeEnum>> value(); }
步骤4:编写通用序列化器
这个序列化器会从字段的注解中获取枚举类,再根据Integer值匹配对应的枚举实例:
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import java.io.IOException; import java.lang.reflect.Field; public class GenericEnumSerializer extends JsonSerializer<Integer> { @Override public void serialize(Integer value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { if (value == null) { jsonGenerator.writeNull(); return; } try { // 获取当前序列化的字段 Field field = serializerProvider.getContextualType().getRawClass() .getDeclaredField(serializerProvider.getPropertyName()); EnumSerialize enumAnnotation = field.getAnnotation(EnumSerialize.class); if (enumAnnotation == null) { jsonGenerator.writeNull(); return; } // 获取枚举类的所有实例 Class<? extends Enum<? extends CodeEnum>> enumClass = enumAnnotation.value(); Enum<? extends CodeEnum>[] enumConstants = enumClass.getEnumConstants(); // 匹配对应code的枚举 for (Enum<? extends CodeEnum> enumInstance : enumConstants) { CodeEnum codeEnum = (CodeEnum) enumInstance; if (codeEnum.getCode().equals(value)) { jsonGenerator.writeObject(enumInstance); return; } } // 未匹配到对应枚举时的处理,可根据需求改为抛出异常 jsonGenerator.writeNull(); } catch (NoSuchFieldException | SecurityException e) { // 字段反射失败时的处理 jsonGenerator.writeNull(); } } }
步骤5:在实体类中使用
在需要转换的Integer字段上同时添加@JsonSerialize和@EnumSerialize注解:
@Data public class ZkUser { private String name; @JsonSerialize(using = GenericEnumSerializer.class) @EnumSerialize(StatusEnum.class) private Integer status; }
补充说明
后续新增需要转换的枚举类时,只需要让枚举实现CodeEnum接口,然后在实体类字段上添加对应的@EnumSerialize注解即可,无需再编写新的序列化器。
内容的提问来源于stack exchange,提问作者realheyu
相关产品推荐
相关产品推荐

