平时在开发的时候难免会遇到枚举来翻译类,于是写一个自定义注解来在开发的时候自动翻译枚举的值
相关代码如下:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@JacksonAnnotationsInside
public @interface EnumShow {
/**
* 要转换成的枚举
*
* @return
*/
Class<? extends BaseEnum<?>> enumClass();
/**
* 如果不复写本身新增字段是本身字段的增加的后缀
*
* @return
*/
String suffix() default "Str";
}
这段Java代码定义了一个名为EnumShow的注解,用于标注字段。该注解有以下功能:
enumClass属性指定要将字段转换成的枚举类,该枚举类需要继承自BaseEnum。
suffix属性指定当新增字段时,字段名称的后缀,默认为"Str"。
这个注解的作用是配合Jackson库将标注了该注解的字段序列化为指定枚举类的JSON格式。
@JsonComponent
public class EnumShowIntegerSerializer extends JsonSerializer<Integer> implements ContextualSerializer {
private EnumShow enumShow;
public EnumShowIntegerSerializer() {
}
public EnumShowIntegerSerializer(final EnumShow enumShow) {
this.enumShow = enumShow;
}
/**
* 序列化整数枚举值。
* 根据枚举类的实现情况,决定如何序列化枚举值。
* 如果枚举类实现了BaseEnum接口,直接通过接口方法获取描述。
* 如果枚举类没有实现BaseEnum接口,通过反射调用getKey和getValue方法获取描述。
*
* @param integer 需要序列化的整数枚举值。
* @param jsonGenerator 用于生成JSON的工具。
* @param serializerProvider 序列化提供者,用于获取其他序列化器。
* @throws IOException 如果序列化过程中发生I/O错误。
*/
@SneakyThrows
@Override
public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
if (null == integer || null == enumShow) {
jsonGenerator.writeObject(integer);
return;
}
String fieldName = jsonGenerator.getOutputContext().getCurrentName();
Class<?>[] interfaces = enumShow.enumClass().getInterfaces();
String theMsg = null;
if (interfaces.length > 0) {
Class<?> baseInterface = interfaces[0];
if (baseInterface.equals(BaseEnum.class)) {
Class newIns = enumShow.enumClass();
Optional<? extends BaseEnum<?>> enumOpt = BaseEnum.of(newIns, integer);
if (enumOpt.isPresent()) {
theMsg = enumOpt.get().getValue();
}
}
} else {
if (enumShow.enumClass().isEnum()) {
Method codeMethod = enumShow.enumClass().getDeclaredMethod("getKey");
Method descMethod = enumShow.enumClass().getDeclaredMethod("getValue");
for (Object obj : enumShow.enumClass().getEnumConstants()) {
if (integer.equals(codeMethod.invoke(obj))) {
theMsg = descMethod.invoke(obj).toString();
}
}
}
}
jsonGenerator.writeNumber(integer);
jsonGenerator.writeStringField(fieldName + enumShow.suffix(), theMsg);
}
/**
* 根据上下文创建自定义的序列化器。
* 如果属性上有EnumShow注解,则创建EnumShowIntegerSerializer;
* 如果没有相关的注解,则返回默认的整数序列化器。
*
* @param serializerProvider 序列化提供者,用于获取其他序列化器。
* @param beanProperty 当前属性的信息,用于获取注解。
* @return 自定义的序列化器或默认的整数序列化器。
* @throws JsonMappingException 如果创建序列化器过程中发生错误。
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
EnumShow annotation = beanProperty.getAnnotation(EnumShow.class);
if (annotation != null) {
return new EnumShowIntegerSerializer(annotation);
}
}
return NumberSerializer.instance;
}
这个Java类是一个自定义的JSON序列化器,用于将Java的整数类型(Integer)序列化为JSON格式。它继承了Jackson库中的JsonSerializer类,并实现了ContextualSerializer接口。
EnumShowIntegerSerializer 类的作用是根据EnumShow注解的配置,对整数类型的枚举值进行序列化时,除了输出数值本身,还会额外输出一个带有特定suffix的字符串字段,该字段的值是根据枚举值的特定规则计算得到的。
serialize 方法用于将整数序列化为JSON。如果传入的整数或enumShow为null,则直接将整数序列化为JSON。否则,根据enumShow的配置获取枚举类,并根据枚举类的特性进行处理:
如果枚举类实现了BaseEnum接口,则通过BaseEnum.of方法获取枚举值,并获取其对应的字符串值。
如果枚举类为普通的Java枚举,则通过反射获取枚举值的键和值方法,并遍历枚举常量,找到对应整数值的枚举值,并获取其值。
createContextual 方法用于根据属性上的注解(EnumShow或DictShow)创建并返回一个适当的自定义序列化器。如果属性上有EnumShow注解,则返回一个新的EnumShowIntegerSerializer实例;如果有DictShow注解,则返回一个新的DictShowIntegerSerializer实例;否则,返回一个默认的数字序列化器NumberSerializer.instance。
这个自定义序列化器可以用于Spring Boot应用程序中,通过@JsonComponent注解将其注册为一个Jackson组件,以便在序列化过程中自动使用。
然后对所需要的属性上加上@EnumShow注解,如下图例子
在测试输出数据后,即可输出一个与之对应字段的翻译。