🥭 Jackson使用手册
一、前言
Jackson 是一款相当优秀的 JSON 解析器,Jackson 有很多优点:解析大文件的速度比较快、运行时占用的内存比较少,性能更佳、API 很灵活,容易进行扩展和定制。核心模块由三部分组成:
- jackson-core核心包,提供基于“流模式”解析的相关 API,包括 JsonPaser 和 JsonGenerator;
- jackson-annotations注解包,提供标准的注解功能;
- jackson-databind 数据绑定包,提供基于“对象绑定”解析的相关 API ( ObjectMapper ) 和基于“树模型”解析的相关 API (JsonNode);
使用 Jackson 分为两种情况:普通 Maven 项目、SpringBoot 项目,前者为独立使用、后者为集成使用。
二、全局配置
Jackson 配置属性类,常见的配置需求包含:全局日期格式、全局字符串序列化顺序(字典排序)、驼峰与下划线转换。
(一)默认配置
默认配置类JacksonProperties,其中需要关注的几个参数如下:
参数 | 含义 | 默认值 | 备注 |
date-format | 日期格式化模式 | 无 | 建议设置yyyy-MM-dd HH:mm:ss |
time-zone | 时区 | 无 | 建议设置GMT+8 |
property-naming-strategy | 属性命名策略 | 无 | 建议设置SNAKE_CASE |
简化配置
spring:
jackson:
date-format: 'yyyy-MM-dd HH:mm:ss'
time-zone: 'GMT+8'
mapper:
# 格式化JSON按照字典顺序排序
sort-properties-alphabetically: true
# 后端传递前端的值由驼峰转下划线,前端传递给后端的参数由下划线转驼峰
property-naming-strategy: SNAKE_CASE
详细配置
spring:
jackson:
# 设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值,SNAKE_CASE-返回的json驼峰式转下划线,json body下划线传到后端自动转驼峰式
property-naming-strategy: SNAKE_CASE
# 全局设置@JsonFormat的格式pattern
date-format: yyyy-MM-dd HH:mm:ss
# 当地时区
locale: zh
# 设置全局时区
time-zone: GMT+8
# 常用,全局设置pojo或被@JsonInclude注解的属性的序列化方式
default-property-inclusion: NON_NULL #不为空的属性才会序列化,具体属性可看JsonInclude.Include
# 常规默认,枚举类SerializationFeature中的枚举属性为key,值为boolean设置jackson序列化特性,具体key请看SerializationFeature源码
serialization:
WRITE_DATES_AS_TIMESTAMPS: true # 返回的java.util.date转换成timestamp
FAIL_ON_EMPTY_BEANS: true # 对象为空时是否报错,默认true
# 枚举类DeserializationFeature中的枚举属性为key,值为boolean设置jackson反序列化特性,具体key请看DeserializationFeature源码
deserialization:
# 常用,json中含pojo不存在属性时是否失败报错,默认true
FAIL_ON_UNKNOWN_PROPERTIES: false
# 枚举类MapperFeature中的枚举属性为key,值为boolean设置jackson ObjectMapper特性
# ObjectMapper在jackson中负责json的读写、json与pojo的互转、json tree的互转,具体特性请看MapperFeature,常规默认即可
mapper:
# 使用getter取代setter探测属性,如类中含getName()但不包含name属性与setName(),传输的vo json格式模板中依旧含name属性
USE_GETTERS_AS_SETTERS: true #默认false
# 枚举类JsonParser.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonParser特性
# JsonParser在jackson中负责json内容的读取,具体特性请看JsonParser.Feature,一般无需设置默认即可
parser:
ALLOW_SINGLE_QUOTES: true # 是否允许出现单引号,默认false
# 枚举类JsonGenerator.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonGenerator特性,一般无需设置默认即可
# JsonGenerator在jackson中负责编写json内容,具体特性请看JsonGenerator.Feature
三、个性化配置
1、属性字典排序
如果不添加任何有关属性顺序的配置,默认按照属性在实体类中的顺序格式化;如果在全局设置对象中属性转 JSON 中字段按照字典顺序排序,则格式化后的字段按照字典顺序排序。如果有特别需求使用注解@JsonPropertyOrder 自定义排序字段排序顺序。
@JsonPropertyOrder({"resName", "checkStatus","buildExportVo"})
public class FirstExportVo {
private String resName;
private Integer checkStatus;
private List<BuildExportVo> buildExportVo = new ArrayList<>();
}
当字段易属性变化时,比如重命名操作,更优雅的解决方式如下:
public class FirstExportVo {
@JsonProperty(index = 1)
private String resName;
@JsonProperty(index = 2)
private Integer checkStatus;
@JsonProperty(index = 3)
private List<BuildExportVo> buildExportVo = new ArrayList<>();
}
2、日期格式
如果在全局配置时间日期格式为yyyy-MM-dd HH:mm:ss,特殊场合下需要yyyy-MM-dd格式的日期,通过如下注解即可实现。添加在字段上的注解优先级比全局配置要高。
@JsonFormat(pattern = DateTimeFormatter.ISO_DATE)
private Date birthDay;
3、驼峰与下划线互转
后端传递前端的值由驼峰转下划线,前端传递给后端的参数由下划线转驼峰。前端向后端传递参数时,下划线表示的参数放在请求体中方才被识别。下划线传参生效后,驼峰规则表示的参数失效。
MyBatis 同样可以配置下划线和驼峰互转,Jackson 在 MVC 层面实现,MyBatis 在 ORM 层面实现。
spring:
jackson:
# 后端传递前端的值由驼峰转下划线,前端传递给后端的参数由下划线转驼峰
property-naming-strategy: SNAKE_CASE
四、使用经验
引入依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.2</version>
</dependency>
jackson-databind 依赖于 jackson-core 和 jackson-annotations,由 maven 自动管理相关依赖,用户无需额外添加。
(一)基础使用
此处的对象是指简单的 POJO,JSON 字段与 Java 对象属性一一对应,不涉及继承关系。
JSON 与对象互转本质上属于序列化与反序列化,相较于一般的二进制序列化,此处为 JSON 字符串的序列化。
1、JSON 转对象
User[] users = objectMapper.readValue(new File("/tmp/111.json"), User[].class);
// JSON串转化为对象(替换占位符)
objectMapper.readValue("JSON串", User[].class);
// 字节数组转化为对象(替换占位符)
objectMapper.readValue(new byte[16], User[].class);
2、对象转 JSON
Jackson 通过writeValue系列方法将 Java 对象序列化为 JSON,支持存储成不同的格式。
ObjectMapper mapper = new ObjectMapper();
// 转化为JSON并存储为文件
mapper.writeValue(new File("/tmp/111.json"),list);
// 转化为JSON字符串
String content = mapper.writeValueAsString(list);
将对象转化为字节数组。
// 转化为字节数组
byte[] bytes = mapper.writeValueAsBytes(list);
(二)新日期类型
新日期常用类LocalDate、LocalDateTime两种,Jackson 在处理新日期类型并不流畅,与其它基础类型相比,需要解决如下两类问题:格式化与序列化。
特点 | 数据流向 | Serializable | |
格式化 | 单向 | 内存对象 —> JSON 串 | 不需要实现 |
序列化 | 双向 | 内存对象 <—> 其它存储介质 | 需要实现 |
1、LocalDate
@Bean
public Jackson2ObjectMapperBuilderCustomizer localDateCustomizer() {
return builder -> builder.serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_DATE));
}
2、LocalDateTime
此处用到了hutool-core包中的DatePattern类。
@Bean
public Jackson2ObjectMapperBuilderCustomizer localDateTimeCustomizer() {
return builder -> builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
}
如果全局配置未生效,直接在实体类中配置
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
@JsonSerialize(using = LocalDateTimeSerializer.class)
(三)高级使用
1、Long
Long类型字段需要进行序列化配置,考虑到前端 JS 不能容纳 Long 类型数据,需要将其转化为字符串,同理前端也应用字符串像后端传递数据。
@Bean
public Jackson2ObjectMapperBuilderCustomizer longCustomizer() {
return builder -> builder.serializerByType(Long.class, ToStringSerializer.instance);
}
2、时间戳格式化
在处理全球化业务过程中,数据库存储的时间格式为 13 位的时间戳(单位:毫秒),下列方式可快速实现日期格式化(屏蔽空指针异常)。
@JsonFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
public LocalDateTime getCreateTime() {
Function<Long, LocalDateTime> mapper = e -> LocalDateTime.ofInstant(Instant.ofEpochMilli(e), ZoneId.systemDefault());
return Optional.ofNullable(this.createTime).map(mapper).orElse(null);
}
解决思路是将时间戳转化为LocalDateTime实例,然后利用默认 Jackson 框架格式化日期输出。
3、空值处理
对于空值,序列化成 JSON 串意义不大,因此可以通过@JsonInclude(JsonInclude.Include.NON_NULL)类注解过滤空值字段。
看完如果有帮助,希望可以给个 三连 ,你的鼓励就是我不断前进的动力。谢谢
关注我:私信获取Java高级架构资料、大厂面试试题、视频