Springboot序列化动态增加字段
前⾔
我们使⽤类型时,返回前段⼀般需要加⼀些字段来标识这个类型的中⽂名。但是这个需要我们⼿动添加⼀个字段,并且在返回时给这个中⽂字段设置值,很⿇烦那有没有更⽅便的做法呢。当然有的,下边我们来学习⼀下序列化动态增加字段。
开始操作
环境:
JDK 1.8 , Spring boot 2.4.3, fastjson 1.2.76
⾸先我们需要定义⼀个枚举,来标识我们哪些字段需要扩展中⽂名称字段
/**
* 功能描述 : 注解序列化
*
* @author ziyear 2021-12-18 19:21
*/
@Inherited
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public@interface EnumSerialize {
/**
* 字段对应枚举的class
*
* @return
*/
Class<?>value();
/**
* 获取中⽂名称的⽅法
*
* @return
*/
String method()default"getMsgByCode";
}
我们再去创建两个枚举吧
⽤户性别枚举
public enum SexEnum {
MAN("man","男"),
WOMAN("woman","⼥"),
;
private final String code;
private final String msg;
public String getCode(){
return code;
}
public String getMsg(){
return msg;
}
SexEnum(String code, String msg){
this.msg = msg;
}
/**
* 根据code获取中⽂描述的⽅法
*/
public static String getMsgByCode(String code){ for(SexEnum sexEnum :values()){
de.equals(code)){
return sexEnum.msg;
}
}
return code;
}
}
⽤户级别枚举
public enum UserLevelEnum {
DEFAULT("default","普通会员"),
ADVANCED("advanced","⾼级会员"),
SUPER("super","⾄尊会员"),
;
private final String code;
private final String msg;
public String getCode(){
return code;
}
public String getMsg(){
return msg;
}
UserLevelEnum(String code, String msg){
this.msg = msg;
}
/
**
* 根据code取名称
*/
public static String getMsg(String code){
for(UserLevelEnum anEnum :values()){
de.equals(code)){
return anEnum.msg;
}
}
return code;
}
}
然后 我们创建⼀个⽤户类 在性别和等级上分别加上注解,指定我们注解中获取中⽂描述的⽅法,因为我们设置了默认⽅法,如果⽅法名和默认⽅法⼀致的话就不需要指定了。
/**
* 功能描述 : ⽤户类
*
* @author ziyear 2021-12-18 19:22
*/
@Data
public class User  {
private Long id;
private String name;
private String mobile;
@EnumSerialize(SexEnum.class)
private String sex;
@EnumSerialize(value = UserLevelEnum.class,method ="getMsg")
springboot中文private String level;
}
下边我们搞⼀个枚举⾃定义序列化类,对字段上包含 EnumSerialize 的类进⾏序列化
/**
* 功能描述 : 枚举⾃定义序列化
*
* @author ziyear 2021-12-18 19:23
*/
@Slf4j
public class EnumsSerializer implements ObjectSerializer {
private static final String FIELD_KEY_EXT ="Name";
private static final String BEAN_START ="{";
private static final String BEAN_END ="}";
private static final String EXT_FIELD_FORMAT =",\"{0}\": \"{1}\"";
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features)throws IOException {
if(object ==null){
serializer.write(object);
return;
}
JavaBeanSerializer javaBeanSerializer =new Class()){
@Override
public void write(JSONSerializer serializer, Object object, Object fieldName, Type fieldType,int features)throws IOException {
super.write(serializer, object, fieldName, fieldType, features,true);
}
};
SerializeWriter out = Writer();
out.write(BEAN_START);
javaBeanSerializer.write(serializer, object, fieldName, fieldType, features);
try{
Set<String> fieldNames = FieldNames(object);
for(String name : fieldNames){
FieldSerializer fieldSerializer = FieldSerializer(name);
Field field = fieldSerializer.fieldInfo.field;
if(field !=null){
final EnumSerialize annotation = AnnotationUtils.findAnnotation(field, EnumSerialize.class);
if(annotation !=null){
Class<?> value = annotation.value();
String methodName = hod();
Method method;
try{
method = Method(methodName, String.class);
}catch(Exception e){
<("⽅法不存在!{}#{}", value, methodName);
continue;
}
Object fieldValue = FieldValue(object, name);
Object msg = method.invoke(null, String(fieldValue));
writeExtField(out, name, msg);
}
}
}
}catch(Exception e){
<("序列化出现错误!", e);
}finally{
out.write(BEAN_END);
}
}
private void writeExtField(SerializeWriter out, String key, Object value){
String format = MessageFormat.format(EXT_FIELD_FORMAT, key + FIELD_KEY_EXT, value);
out.write(format);
}
}
⾃定义序列化搞好了,然后我们需要将我们的序列化配置到消息转换器中,这样在序列化输出的时候就能⽤上我们的⾃定义序列化了
/**
* 功能描述 : 配置类
*
* @author Ziyear 2021-12-18 19:32
*/
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters){
FastJsonHttpMessageConverter fastJsonConverter =new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig =new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.QuoteFieldNames,
SerializerFeature.WriteEnumUsingToString,
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteNullStringAsEmpty);
JSON.DEFAULT_GENERATE_FEATURE |= Mask();        fastJsonConverter.wArrayList(MediaType.APPLICATION_JSON_UTF8, new MediaType(MediaType.TEXT_HTML, StandardCharsets.UTF_8),
new MediaType(MediaType.APPLICATION_FORM_URLENCODED, StandardCharsets.UTF_8)));
/
/ 序列化配置
SerializeConfig serializeConfig =new SerializeConfig(){
@Override
public ObjectSerializer getObjectWriter(Class<?> clazz){
// 从类⾥⾯寻注解,如果字段上包含枚举序列化注解的话,我们就⾛到
final EnumSerialize annotation =findClassFiledAnnotation(clazz, EnumSerialize.class);
if(annotation !=null){
return new EnumsSerializer();
}
ObjectWriter(clazz);
}
};
fastJsonConfig.setSerializeConfig(serializeConfig);
fastJsonConverter.setFastJsonConfig(fastJsonConfig);
converters.add(fastJsonConverter);
}
public static<A extends Annotation> A findClassFiledAnnotation(Class<?> clazz, Class<A> annotation){
Field[] declaredFields = DeclaredFields();
for(Field declaredField : declaredFields){
A result = Annotation(annotation);
if(result !=null){
return result;
}
}
return null;
}
}
配置完成
我们搞⼀个接⼝试试