Jackson使用总结

前言

这么多序列化工具,自己最喜欢的还是Jackson,关于它的学习一直是零零散散的学习,用到什么去找什么,现在在这里做个总结

依赖引入

1
2
3
4
5
6
7
8
9
10
11
12
13
        <!--jackson-->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- <dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>-->

jackson-databind已经包含了jackson-corejackson-annotations,所以我们引入一个就可以了

  • jackson-core,核心包,提供基于”流模式”解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json
  • jackson-annotations,注解包,提供标准注解功能;
  • jackson-databind ,数据绑定包, 提供基于”对象绑定” 解析的相关 API ( ObjectMapper ) 和”树模型” 解析的相关 API (JsonNode);基于”对象绑定” 解析的 API 和”树模型”解析的 API 依赖基于”流模式”解析的 API。

Jackson 使用

我们使用 Jackson 无非是为了序列化和反序列化,Jackson 通常的序列化对象为ObjectMapper,我们可以通过配置该对象的属性来达到定制化序列化的效果,但是通常情况下,只需要简单的序列化即可

基本用法

1. 对象序列化和反序列化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private static final ObjectMapper MAPPER = new ObjectMapper();

@SneakyThrows
public static String toJson(Object object) {
if (null == object) {
return "";
}
return MAPPER.writeValueAsString(object);
}

@SneakyThrows
public static <T> T parseJson(String json, Class<T> valueType) {
return MAPPER.readValue(json, valueType);
}

注意

  1. 这里的序列化指的是简单对象,即对象中依然包含对象是不支持的,带泛型的 List 也是不支持

2. 注解使用

注解 用法
@JsonProperty 用于属性,把属性的名称序列化时转换为另外一个名称。示例: @JsonProperty(“birth_ d ate”) private Date birthDate;
@JsonFormat 用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例: @JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) public Date getBirthDate()
@JsonPropertyOrder 用于类, 指定属性在序列化时 json 中的顺序 , 示例: @JsonPropertyOrder({ “birth_Date”, “name” }) public class Person
@JsonCreator 用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。 示例: @JsonCreator public Person(@JsonProperty(“name”)String name) {…}
@JsonAnySetter 用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 @JsonAnySetter public void set(String key, Object value) { map.put(key, value); }
@JsonAnyGetter 用于方法 ,获取所有未序列化的属性 public Map<string, object> any() { return map; }

3. SprinBoot 的序列化设置

我们知道 Spingboot 默认的序列化方式都是 jackson,当然你也可以自己以其他比如 FastJSON 的方式去替换掉,这里只谈Jackson

  1. 很多时候 SpringBoot 对于前端参数解析,也就是序列化的时候,一些日期格式是不支持,比如旧版本的不支持yyyy-MM-dd hh:mm:ss日期格式,这会导致麻烦的解析失败,耽误时间
  2. 回传数据给前端时,数据反序列化格式不统一,LocalDateTime数据类型包含了一个 T
  3. Jackson 默认时区为 UTC,当发现操作系统时区为 GMT+8 时,会将原时间加上 8 小时返回,这个算个坑,踩过了就还好

关于第一个问题第三个问题可以在 application.yml 中配置

1
2
3
4
spring:
jackson:
time-zone: GMT+8
date-format: "yyyy-MM-dd HH:mm:ss"

也可以在项目中使用配置类配置,个人推荐使用第二种,尤其是在大型项目中,这块可以放到公用依赖中,方便复用
以下是通过配置类方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
public class SpringJsonConfig {
/**
* 标准日期
*/
private static final String DATE_PATTERN = "yyyy-MM-dd";

/**
* 标准日期时间
*/
private static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";


@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder ->{
jacksonObjectMapperBuilder.simpleDateFormat(DATE_PATTERN);
jacksonObjectMapperBuilder.serializerByType(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DATE_PATTERN)));
jacksonObjectMapperBuilder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_PATTERN)));
jacksonObjectMapperBuilder.timeZone(TimeZone.getTimeZone("GMT+8"));
jacksonObjectMapperBuilder.serializationInclusion(JsonInclude.Include.NON_NULL);
};
}
}

4. ObjectMapper 的常用配置

对于 ObjectMapper 的配置,通常是在 Json 工具类中配置好来使用,最好可以配置上默认的设置,方便使用

1
2
3
4
5
6
7
8
9
10
//忽略不识别的字符串
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//允许原始值为null
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
//允许枚举转换为数字
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
//序列化时null值自动忽略
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//日期格式化模式
objectMapper.setDateFormat(new SimpleDateFormat(DATE_PATTERN));

高阶用法

  1. 自定义序列化器

相关

作者

孙博文

发布于

2020-06-28

更新于

2021-07-18

许可协议

评论