场景: 在设计数据库时,我们通常会建立一个dict表,存储了项目内所有的字典名称和字典值,例如用户等级、用户职称等字典,然后其他表内的存储的值是dict_code,前端展示需要将dict_code映射为dict_value。
示例: User表有个sourceType字段(1=微信、2=在发版),返回给前端时需要返回sourceType(dict_code),和sourceTypeName(dict_key)。
实现方案: 通过自定义JsonSerializer方式实现枚举值的动态转换。
- 定义注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DictTranslationSerialize.class)
public @interface DictTranslation {
/**
* 数据库内的 dict_key
*/
String dictKey();
/**
* 转换后的json字段名称
* @return
*/
String targetFieldName() default "";
}
- 继承JsonSerializer,自定义序列化规则。
@AllArgsConstructor
@NoArgsConstructor
public class DictTranslationSerialize extends JsonSerializer<Object> implements ContextualSerializer {
private String dictKey;
private String sourceFieldName;
private String fieldName;
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String codeValue = o.toString();
jsonGenerator.writeString(codeValue);
//模拟查询数据库 select * from dict where dict_key = #{dictKey};
String dictValue = "dictValue="+dictKey;
//如果没有指定生成的字段值,则去原字段的名字加Value后缀。
fieldName = Objects.isNull(fieldName) || fieldName.trim().isEmpty() ? sourceFieldName+"Value" : fieldName;
//写入json
jsonGenerator.writeFieldName(fieldName);
jsonGenerator.writeObject(dictValue);
//还可以继续写其他的东西
jsonGenerator.writeFieldName("serialized");
jsonGenerator.writeObject(true);
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
if (beanProperty != null) {
DictTranslation t = beanProperty.getAnnotation(DictTranslation.class);
if (t != null) {
return new DictTranslationSerialize(t.dictKey(), beanProperty.getName(), t.targetFieldName());
}
}
return serializerProvider.findNullValueSerializer(beanProperty);
}
}
- eneity类上添加注解
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class Student {
@DictTranslation(dictKey = "helloWorld")
private String sourceType;
}