定制Jackson注解实现字段脱敏
功能
在保证jackson原注解不失效的前提下,通过自定义注解对POJO中部分指定的字段进行自定义处理
完成样式
1 |
|
运行结果
1 |
|
核心逻辑
实现逻辑比较简单,核心类只有两个:
- Jackson注解拦截器 com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector
- Json序列化器 com.fasterxml.jackson.databind.JsonSerializer
Jackson序列化逻辑:
- 首先看到这里
com.fasterxml.jackson.databind.ObjectMapper#_configAndWriteValue
,
这个方法根据objectMapper实例中的config创建对应的JsonGenerator
并序列化value。 - 追踪到
com.fasterxml.jackson.databind.ser.DefaultSerializerProvider#serializeValue
根据源码可知,在序列化时使用哪个JsonSerializer是由com.fasterxml.jackson.databind.SerializerProvider#findTypedValueSerializer
决定的,SerializerProvider.findTypedValueSerializer
就是序列化器提供者.根据value类型查找序列化器
。 - !(三句源码注释)[]根据三句源码注释可知,jackson在这里维护了一个本地缓存一个共享缓存,在两个缓存都没找到的时候再通过
com.fasterxml.jackson.databind.SerializerProvider#findValueSerializer
获取新的序列化器并存入缓存。 - 进入到
com.fasterxml.jackson.databind.SerializerProvider#findValueSerializer
内部,再次进行了缓存查找,
在都没有命中的情况下,调用com.fasterxml.jackson.databind.SerializerProvider[521]
的_createAndCacheUntypedSerializer
去创建序列化器。 - 快进到
com.fasterxml.jackson.databind.ser.BeanSerializerFactory#createSerializer
,这里是构建序列化器的真实逻辑。注意下findSerializerFromAnnotation(prov, beanDesc.getClassInfo())
这个方法,
根据方法名直译就是根据注解获取序列化器
。 - 进入到
com.fasterxml.jackson.databind.ser.BasicSerializerFactory#findSerializerFromAnnotation
内部,发现Jackson获取序列化器分为两步:- 调用
prov.getAnnotationIntrospector().findSerializer(a)
找到序列化器的class,随后在prov.serializerInstance(a, serDef)
中实例化改序列化器 - 调用
prov.getAnnotationIntrospector().findSerializer(a)
直接获取JsonSerializer
类型的实例,随后在prov.serializerInstance(a, serDef)
中强转为JsonSerializer<?>
- 调用
- 快进到
com.fasterxml.jackson.databind.AnnotationIntrospector#findSerializer
,这里具体使用的是JacksonAnnotationIntrospector
类。这个类中定义了jackson中的序列化和反序列化有关的注解及其对应的处理方式。 - 进入到
com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector.findSerializer
,发现这里处理了两个注解@JsonSerialize
、@JsonRawValue
,找到注解的情况下new出了对应的序列化器,没有找到任何注解返回了null。 - 到此为止=====
根据上面整理的逻辑。要想jackson处理自定义注解,就必须给jackson配置一个自定义的AnnotationIntrospector
,如果这里手动实现AnnotationIntrospector
接口,那么jackson自带的注解都会失效,因此选择继承原有的JacksonAnnotationIntrospector
类。
在这个类中,可以通过返回不同的序列化器来控制序列化的具体行为,其方法入参Annotated
类实际上是对被序列化字段的类型的包装。但注意,在AnnotationIntrospector
中是无法拿到被序列化的值本身的,只能拿到字段的相关信息。
重写
重写JacksonAnnotationIntrospector 增强Jackson注解处理器
1 |
|
重写JsonSerializer 序列化器
1 |
|