前言
SpringBoot默认使用Jackson进行json数据的序列化,在这个过程中总会有些奇奇怪怪的需求,对于这些小需求要么增加一堆配置类,要么重写方法,其实都有点杀鸡用牛刀了,那么我来列举下日常开发中这些小需求如何通过配置的形式解决。
1 值的格式化
1.1 日期类型显示为 yyyy-MM-dd HH:mm:ss
- 字段级别配置
@Data
public class MyClass {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime time1;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timeZone = "GMT+8")
private Date time2;
}
- 类级别配置
@Data
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timeZone = "GMT+8")
public class MyClass {
private LocalDateTime time1;
private Date time2;
}
- 全局配置
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
1.2 Long型字段序列化成字符串
Java的Long字段在Javascript中会精度丢失,所以序列化时要将该字段序列化成String
- 字段级别配置
@Data
public class MyClass {
@JsonFormat(shape = JsonFormat.Shape.STRING)
private Long lng;
}
- 类级别配置 (会将所有的字段都以字符串形式展示)
@Data
@JsonFormat(shape = JsonFormat.Shape.STRING)
public class MyClass {
private Long lng;
}
2 JSON字段值的选择
2.1 用某个字段值来代替对象值
使用@JsonValue注解可以在序列化时只序列化其中某一个属性的值,而不是全部对象
@Data
public class Parent {
public int age;
public Name name;
@Data
public static class Name {
@JsonValue
public String firstName;
public String lastName;
}
}
结果示例:{ “age”: 25, “name”: “Wang”}, 而不是 { “age”: 25, “name”: { “firstName”: “Wang”, “lastName”: “Lei”}}
3 字段名形式
3.1 字段名显示为下划线分隔形式
- 字段级别配置
@Data
public class MyClass {
@JsonProperty("user_name")
private String userName;
}
- 类级别配置
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class MyClass {
private String userName;
}
其他形式示例
SnakeCaseStrategy
“user_name”UpperSnakeCaseStrategy
“USER_NAME”UpperCamelCaseStrategy
“UserName”LowerCamelCaseStrategy
“userName”LowerCaseStrategy
“username”LowerDotCaseStrategy
“user.name”KebabCaseStrategy
“user-name”
- 全局配置
spring:
jackson:
property-naming-strategy: SNAKE_CASE
其他形式示例
SNAKE_CASE
“user_name”UPPER_SNAKE_CASE
“USER_NAME”UPPER_CAMEL_CASE
“UserName”LOWER_CAMEL_CASE
“userName”LOWER_CASE
“username”LOWER_DOT_CASE
“user.name”KEBAB_CASE
“user-name”
4 字段显示与忽略
4.1 只显示非空字段
@Data
public class MyClass {
@JsonInclude(JsonInclude.Include.NON_NULL)
private String userName;
}
- 类级别配置
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class MyClass {
private String userName;
}
其他筛选策略
ALWAYS
始终包含,和属性的值无关NON_NULL
值非空的属性才会包含属性NON_ABSENT
值非空的属性,或者Optional类型的属性非空NON_EMPTY
空值的属性不包含CUSTOM
自定义规则
4.2 忽略某个属性
使用@JsonIgnore注解可以忽略某个字段
@Data
public class Parent {
public int age;
public Name name;
@Data
public static class Name {
public String firstName;
@JsonIgnore
public String lastName;
}
}
结果示例: { “age”: 25, “name”: { “firstName”: “Wang”}}, 而不是 { “age”: 25, “name”: { “firstName”: “Wang”, “lastName”: “Lei”}}
4.3 动态字段
使用@JsonAnyGetter
注解将会使dynamicMap中的所有key当成和userName同级别的字段,一同被序列化:
@Data
public class MyClass {
private String userName;
@JsonAnyGetter
private Map<String, Object> dynamicMap;
}
而使用@JsonAnySetter
在反序列化时,会把除userName以外的字段都存放在dynamicMap对象中,需要注意的是,这时dynamicMap需要初始化:
@Data
public class MyClass {
private String userName;
@JsonAnySetter
private Map<String, Object> dynamicMap = new HashMap<>();
}
4.4 将子对象的内容展开到父对象
使用@JsonUnwrapped
注解将会使该字段的内容展开序列化到父级:
@Data
public class Parent {
public int age;
@JsonUnwrapped
public Name name;
@Data
public static class Name {
public String firstName;
public String lastName;
}
}
结果示例:{ “age”: 25, “firstName”: “John”, “lastName”: “Smith”}, 而不是 { “age”: 25, “name”: { “firstName”: “John”, “lastName”: “Smith”}}