mirror of https://gitee.com/stylefeng/roses
【7.2.5】【wrapper】优化针对json响应数据的自定义格式化
parent
aeaf4936be
commit
f053734a35
|
@ -45,11 +45,11 @@ public @interface JsonFieldFormat {
|
||||||
* <p>
|
* <p>
|
||||||
* 默认采用包装型,不改变原有的字段
|
* 默认采用包装型,不改变原有的字段
|
||||||
*/
|
*/
|
||||||
FormatTypeEnum formatType() default FormatTypeEnum.WRAPPER;
|
FormatTypeEnum formatType() default FormatTypeEnum.ADD_FIELD;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 具体处理值转化的过程
|
* 具体处理值转化的过程
|
||||||
*/
|
*/
|
||||||
Class<? extends JsonFieldFormatProcess> process();
|
Class<? extends JsonFieldFormatProcess> processClass();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,15 +11,15 @@ public enum FormatTypeEnum {
|
||||||
/**
|
/**
|
||||||
* 替换型,将原有字段替换成新的值
|
* 替换型,将原有字段替换成新的值
|
||||||
* <p>
|
* <p>
|
||||||
* 例如:接口返回userId=1001,采用本种方式则返回userId=张三
|
* 例如:接口返回userId=1001,采用本种方式则返回:userId=张三
|
||||||
*/
|
*/
|
||||||
REPLACE,
|
REPLACE,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 包装型,不改变原来字段值,在同级别字段中,增加一个 “源字段名+Wrapper" 字段
|
* 额外加字段,不改变原来字段值,在同级别字段中,增加一个 “源字段名+Wrapper" 字段
|
||||||
* <p>
|
* <p>
|
||||||
* 例如:接口返回userId=1001,采用本种方式则返回userIdWrapper=张三
|
* 例如:接口返回userId=1001,采用本种方式则返回:userId=1001,userIdWrapper=张三
|
||||||
*/
|
*/
|
||||||
WRAPPER
|
ADD_FIELD
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>wrapper-api</module>
|
<module>wrapper-api</module>
|
||||||
|
<module>wrapper-field-sdk</module>
|
||||||
<module>wrapper-sdk</module>
|
<module>wrapper-sdk</module>
|
||||||
<module>wrapper-spring-boot-starter</module>
|
<module>wrapper-spring-boot-starter</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
|
@ -42,4 +42,9 @@ public interface WrapperConstants {
|
||||||
*/
|
*/
|
||||||
String WRAPPER_EXCEPTION_STEP_CODE = "24";
|
String WRAPPER_EXCEPTION_STEP_CODE = "24";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 被包装字段,新建字段的结尾字段名
|
||||||
|
*/
|
||||||
|
String FILED_WRAPPER_SUFFIX = "Wrapper";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
# 字段转化模块
|
||||||
|
|
||||||
|
通过json的序列化定制,将ID或者枚举值相关的字段,转化成可以前段直接读懂的名称
|
||||||
|
|
||||||
|
## 示例1
|
||||||
|
|
||||||
|
http响应时,转化userId为用户的名字:
|
||||||
|
|
||||||
|
Long userId; -> "张三"
|
||||||
|
|
||||||
|
## 示例2
|
||||||
|
|
||||||
|
http响应时,转化status为状态的名字:
|
||||||
|
|
||||||
|
Integer status; -> "启用"
|
||||||
|
|
||||||
|
## 示例3
|
||||||
|
|
||||||
|
http响应时,转化枚举为对应的名称:
|
||||||
|
|
||||||
|
StatusEnum status; -> "禁用"
|
||||||
|
|
||||||
|
## 示例4
|
||||||
|
|
||||||
|
http响应时,转化一组数组:
|
||||||
|
|
||||||
|
List<Long> userIdList; -> ["张三","李四","王五"]
|
||||||
|
|
||||||
|
## 其他拓展
|
||||||
|
|
||||||
|
只要按接口规范,可以拓展任何相关值的转化
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>cn.stylefeng.roses</groupId>
|
||||||
|
<artifactId>kernel-d-wrapper</artifactId>
|
||||||
|
<version>7.2.5</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>wrapper-field-sdk</artifactId>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!--wrapper模块的api-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.stylefeng.roses</groupId>
|
||||||
|
<artifactId>wrapper-api</artifactId>
|
||||||
|
<version>${roses.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--jackson相关基础依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,41 @@
|
||||||
|
package cn.stylefeng.roses.kernel.wrapper.field;
|
||||||
|
|
||||||
|
import cn.stylefeng.roses.kernel.rule.annotation.JsonFieldFormat;
|
||||||
|
import cn.stylefeng.roses.kernel.rule.base.JsonFieldFormatProcess;
|
||||||
|
import cn.stylefeng.roses.kernel.rule.enums.FormatTypeEnum;
|
||||||
|
import cn.stylefeng.roses.kernel.wrapper.field.serializer.CustomJsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.introspect.Annotated;
|
||||||
|
import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Json序列化,注解拦截器,针对自定义注解@JsonFieldFormat进行拓展性序列化
|
||||||
|
*
|
||||||
|
* @author fengshuonan
|
||||||
|
* @date 2022/9/6 13:56
|
||||||
|
*/
|
||||||
|
public class CustomJacksonIntrospector extends JacksonAnnotationIntrospector {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列化
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 3159434791568421355L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object findSerializer(Annotated annotated) {
|
||||||
|
JsonFieldFormat formatter = annotated.getAnnotation(JsonFieldFormat.class);
|
||||||
|
|
||||||
|
if (formatter == null || formatter.processClass() == null) {
|
||||||
|
return super.findSerializer(annotated);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取格式化处理的方式
|
||||||
|
FormatTypeEnum formatTypeEnum = formatter.formatType();
|
||||||
|
|
||||||
|
// 获取具体的处理方法
|
||||||
|
Class<? extends JsonFieldFormatProcess> process = formatter.processClass();
|
||||||
|
|
||||||
|
// 创建对应的序列化模式
|
||||||
|
return new CustomJsonSerializer(formatTypeEnum, process);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package cn.stylefeng.roses.kernel.wrapper.field.serializer;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ClassUtil;
|
||||||
|
import cn.stylefeng.roses.kernel.rule.base.JsonFieldFormatProcess;
|
||||||
|
import cn.stylefeng.roses.kernel.rule.enums.FormatTypeEnum;
|
||||||
|
import cn.stylefeng.roses.kernel.wrapper.api.constants.WrapperConstants;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator;
|
||||||
|
import com.fasterxml.jackson.databind.JsonSerializer;
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 针对@JsonFieldFormat注解的具体序列化过程
|
||||||
|
*
|
||||||
|
* @author fengshuonan
|
||||||
|
* @date 2022/9/6 14:09
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CustomJsonSerializer extends JsonSerializer<Object> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列化类型,覆盖还是wrapper模式
|
||||||
|
*/
|
||||||
|
private final FormatTypeEnum formatTypeEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具体序列化过程
|
||||||
|
*/
|
||||||
|
private final Class<? extends JsonFieldFormatProcess> processClass;
|
||||||
|
|
||||||
|
public CustomJsonSerializer(FormatTypeEnum formatTypeEnum, Class<? extends JsonFieldFormatProcess> processClass) {
|
||||||
|
this.formatTypeEnum = formatTypeEnum;
|
||||||
|
this.processClass = processClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void serialize(Object originValue, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) {
|
||||||
|
|
||||||
|
// 序列化字段名称
|
||||||
|
String fieldName = jsonGenerator.getOutputContext().getCurrentName();
|
||||||
|
|
||||||
|
// 创建具体字段转化的实现类
|
||||||
|
JsonFieldFormatProcess jsonFieldFormatProcess = null;
|
||||||
|
try {
|
||||||
|
jsonFieldFormatProcess = processClass.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
log.error("执行json的字段序列化出错", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断当前字段值是否可以转化
|
||||||
|
boolean canFormat = jsonFieldFormatProcess.canFormat(originValue);
|
||||||
|
if (!canFormat) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行转化,获取转化过的值
|
||||||
|
Object formattedValue = jsonFieldFormatProcess.formatProcess(originValue);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 如果转化模式是替换类型
|
||||||
|
if (formatTypeEnum.equals(FormatTypeEnum.REPLACE)) {
|
||||||
|
jsonGenerator.writeObject(formattedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果转化模式是新增一个包装字段
|
||||||
|
else {
|
||||||
|
// 先写入原有值,保持不变
|
||||||
|
jsonGenerator.writeObject(originValue);
|
||||||
|
|
||||||
|
// 构造新的字段名,为原字段名+Wrapper
|
||||||
|
String newWrapperFieldName = fieldName + WrapperConstants.FILED_WRAPPER_SUFFIX;
|
||||||
|
|
||||||
|
// 获取当前正在转化的对象
|
||||||
|
Object currentObj = jsonGenerator.getOutputContext().getCurrentValue();
|
||||||
|
|
||||||
|
// 如果当前正在转化的对象中已经含有了字段名+Wrapper的字段,则生成时候带一个数字2
|
||||||
|
Field declaredField = ClassUtil.getDeclaredField(currentObj.getClass(), newWrapperFieldName);
|
||||||
|
if (declaredField != null) {
|
||||||
|
newWrapperFieldName = newWrapperFieldName + "2";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入新的字段名
|
||||||
|
jsonGenerator.writeFieldName(newWrapperFieldName);
|
||||||
|
jsonGenerator.writeObject(formattedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("执行json的字段序列化出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,6 +24,13 @@
|
||||||
<version>${roses.version}</version>
|
<version>${roses.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--对字段的包装和转化-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.stylefeng.roses</groupId>
|
||||||
|
<artifactId>wrapper-field-sdk</artifactId>
|
||||||
|
<version>${roses.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
Loading…
Reference in New Issue