0
点赞
收藏
分享

微信扫一扫

Jackson使用手册

是她丫 2022-02-21 阅读 86

🥭 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:

    # 设置属性命名策略,对应jacksonPropertyNamingStrategy中的常量值,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特性

    # ObjectMapperjackson中负责json的读写、jsonpojo的互转、json tree的互转,具体特性请看MapperFeature,常规默认即可

    mapper:

      # 使用getter取代setter探测属性,如类中含getName()但不包含name属性与setName(),传输的vo json格式模板中依旧含name属性

      USE_GETTERS_AS_SETTERS: true #默认false

    # 枚举类JsonParser.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonParser特性

    # JsonParserjackson中负责json内容的读取,具体特性请看JsonParser.Feature,一般无需设置默认即可

    parser:

      ALLOW_SINGLE_QUOTES: true # 是否允许出现单引号,默认false

    # 枚举类JsonGenerator.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonGenerator特性,一般无需设置默认即可

    # JsonGeneratorjackson中负责编写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 自动管理相关依赖,用户无需额外添加。

(一)基础使用

此处的对象是指简单的 POJOJSON 字段与 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);

(二)新日期类型

新日期常用类LocalDateLocalDateTime两种,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高级架构资料、大厂面试试题、视频

举报

相关推荐

0 条评论