通过Jackson实现敏感词过滤和类型转换的功能
背景
目前正在做老项目迁移重构工作(Clojure转Java),因历史原因项目中给到端上的Json数据中和(id/user_id/order_id)等相关的id字段需要以string类型给到端上。
已有clojure实现
祖传项目是通过clojure实现的,clojure是一门弱语言和JavaScript一样任何对象都是看做一个map,所以在clojure里面针对这个long->string的功能,实现起来很简单;只需要递归遍历map判断key是否存在于定义的set里面即可,如果满足条件,直接根据是否为list进行toString的处理;
需要实现的功能
实现一个Java方法,传入一个对象进行返回序列化的Json字符串。序列化的同时如果遇到满足条件的字段需要对该字段进行 toString 处理,如果是List<Objec>需要转换为 List<String>。
如何通过Java实现?
因为项目中使用的是jackson序列化json,所以很容易想到的就是使用jackson提供的AnnotationIntrospector,在对应的字段上添加 注解 ,然后自定义AnnotationIntrospector在匹配对应注解的时候返回自定义的Serializer。
tips:仅使用@JsonSerialize(using = ToStringSerializer.class)是不能处理 List<Long> -> List<String>这种情况的
AnnotationIntrospector 实现 long->toString 功能
扩展-AnnotationIntrospector 实现 字段过滤 功能(也可以注解增加属性,用于指定环境过滤等功能)
这里字段过滤其实功能只相当于 @JsonIgnore ,需要增加CustomToString的属性,比如 env;然后在DefaultAnnotationIntrospector中根据env值再做判断
AnnotationIntrospector实现分析
副作用
优化升级
通过对 new ObjectMapper().writeValueAsString() 的执行流程 debug分析,发现对象的属性都被解析成 BeanProperty了,然后会调用 SerializerProvider 的方法寻找合适的Serializer进行序列化
实现 long->toString 功能
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.databind.ser.SerializerFactory;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ObjectUtils;
/**
* @class-name: IdFieldToStringSerializerProvider
* @description:
* @author: Mr.Zeng
*/