文章目录
- 基本模型介绍
- 序列化器
- 注解内省器
- 处理过程简述
- 寻找合适的序列化器
- 序列化器二次处理
- 执行序列化
- 总结
工作中经常用到json序列化,尤其是使用springboot时默认的Jackson序列化框架。 本文主要解析Jackson如何序列化带有注解的字段。
这里以Jackson中常用的@JsonFormat注解为例,目标就是将Company对象序列化。
public class Company {
/**
* 开张时间
*/
@JsonFormat(pattern = "yyyy-MM-dd")
private Date openDate;
public Date getOpenDate() {
return openDate;
}
public void setOpenDate(Date openDate) {
this.openDate = openDate;
}
}
public class Test {
public static void main(String[] args) {
Company company = new Company();
company.setOpenDate(new Date());
ObjectMapper objectMapper = new ObjectMapper();
String s;
try {
s = objectMapper.writeValueAsString(company);
System.out.println(s);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
执行结果如下:
{"openDate":"2023-02-05"}
基本模型介绍
序列化器
序列化器指的是包含对某种类型的数据的序列化方式的类。如自带的有:对String类型序列化的StringSerializer,对Date类型序列化的DateSerializer,对Bean序列化的BeanSerializer。
注解内省器
注解内省器主要是用来判断 标识了注解的数据 该用什么序列化器处理。
处理过程简述
- 寻找合适的序列化器
- 序列化器二次处理(主要用于传递属性元信息)
- 执行序列化
寻找合适的序列化器
- 根据当前数据类型从缓存中获取对应的序列化器
- 如果获取不到,则创建序列化器
- 根据
Company
上的注解获取序列化器(Company
上没有注解) - 根据当前的注解内省器获取能够处理 步骤3 拿到的注解的序列化器(默认的注解内省器是
JacksonAnnotationIntrospector
,对于注解@JsonSerialize
则返回注解指定的序列化器,对于注解JsonRawValue
则返回RawSerializer
) - 如果获取不到,再根据是否实现了
JsonSerializable
接口或者标注了@JsonValue
注解获取对应的序列化器(当前Company
都没有) - 如果没有,就只能创建通用的对象处理器
BeanSerialzer
- 在创建
BeanSerialzer
之前,需要先去找到对象的属性元信息 - 为对象的属性(即
Compnay.openDate
)找到合适的序列化器(类似上面的步骤,一步一步找,这里最终没有找对于openDate
属性的序列化器) - 把属性元信息设置到对象元信息里,然后new一个
BeanSerialzer
并返回 - 拿到返回的序列化器以后,如果该序列化器实现了
ContextualSerializer
接口,则调用它的createContextual
方法进行二次处理,并返回序列化器
序列化器二次处理
上面的步骤10即为序列化器二次处理:当找到合适的序列化器以后,还需要根据是否这个序列化器实现了ContextualSerializer
接口,该接口声明了方法JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property)
该接口可以拿到属性的元信息,如属性上的注解信息,根据元信息可以做一些二次处理,然后再返回序列化器,再用这个返回的序列化器做序列化处理。
执行序列化
- 序列化对象
- 序列化对象的字段
- 动态获取能处理字段的序列化器
- 检索内置的序列化器集合
- 根据类型从内置的序列化器集合获取对应的序列化器,即根据
openDate
的类型Date.class
获取到DateSerializer
- 序列化器二次处理
- 设置需要传递到序列化器中的上下文信息
- 将
openDate
上的JsonFormat
注解的pattern
字段值传递到DateSerializer
,用来在序列化openDate
时知道应该转为哪种时间格式 - 调用
DateSerializer.serialze
进行字段序列化
总结
经过上面的分析,知道了Jackson如何序列化@JsonFormat
标注的字段。
那能否自己定义一个注解,让Jackson通过自定义的序列化器来处理该注解标注的字段🤔️?且等下篇文章再来探究~