- 导入Jackson所需的依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<!--对localDateTime等jdk8时间日期api的转换支持-->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.10.1</version>
</dependency>
- 可以看到 jsr310 依赖是包含 databind 依赖的
1. 序列化
1.1 只包含非 null 属性
- 默认是包含 null
@Test
public void test1() throws JsonProcessingException {
Person person = new Person();
person.setId(1);
// person.setName("兮动人");
person.setAge(20);
person.setBirthDate(new Date());
person.setAddress("深圳市");
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
}
1.1.1 全局配置
- 配置不包含 null,全局配置
private static ObjectMapper objectMapper = new ObjectMapper();
static {
/**
* 序列化的配置
*/
// 全局配置:配置序列化时只包含非空属性
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
/**
* 序列化
*/
@Test
public void test1() throws JsonProcessingException {
Person person = new Person();
person.setId(1);
// person.setName("兮动人");
person.setAge(20);
person.setBirthDate(new Date());
person.setAddress("深圳市");
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
}
1.1.2 单个 bean 配置
- 单个 bean 配置指定非空
1.2 日期时间格式化
@Data
public class Person {
private Integer id;
private String name;
private Integer age;
private String address;
private boolean flag;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date birthDate;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private LocalDateTime registerDate;
}
private static ObjectMapper objectMapper = new ObjectMapper();
static {
/**
* 序列化的配置
*/
// 配置序列化时只包含非空属性
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
}
/**
* 序列化
*/
@Test
public void test1() throws JsonProcessingException {
Person person = new Person();
person.setId(1);
person.setName("兮动人");
person.setAge(20);
person.setBirthDate(new Date());
person.setAddress("深圳市");
person.setRegisterDate(LocalDateTime.now());
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
}
- 可以看到只有 Date birthDate 属性转换成功了,LocalDateTime registerDate 格式是没有转换的
1.2.1 全局配置
- 加上 全局配置:自动通过spi发现 Jackson 的module并注册
static {
/**
* 序列化的配置
*/
// 配置序列化时只包含非空属性
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
/**
* 全局配置:自动通过spi发现 Jackson 的module并注册
*
*/
objectMapper.findAndRegisterModules();
}
1.2.2 单个 bean 配置
- 手动配置
private static ObjectMapper objectMapper = new ObjectMapper();
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
static {
/**
* 序列化的配置
*/
// 配置序列化时只包含非空属性
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
/**
* 全局配置:自动通过spi发现 Jackson 的module并注册
*/
// objectMapper.findAndRegisterModules();
//手动配置 JavaTimeModule 并注册
JavaTimeModule javaTimeModule = new JavaTimeModule();
// 序列化
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
// 反序列化
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)));
// 注册
objectMapper.registerModule(javaTimeModule);
}
- 可以看到 LocalDateTime 类型也可以通过手动配置的方式实现格式化效果
1.3 序列化的美化输出
// 序列化的美化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
2. 反序列化
2.1 忽略不存在的 key
private static ObjectMapper objectMapper = new ObjectMapper();
@Test
public void test2() throws JsonProcessingException {
String str = "{\n" +
" \"id\" : 1,\n" +
" \"name\" : \"兮动人\",\n" +
" \"age\" : 20,\n" +
" \"address\" : \"深圳市\",\n" +
" \"flag\" : false,\n" +
" \"birthDate\" : \"2022-10-09 15:29:56\",\n" +
" \"registerDate\" : \"2022-10-09 15:29:56\"\n" +
"}";
Person person = objectMapper.readValue(str, Person.class);
System.out.println(person);
}
- 如果在JSON字符串中加入个没有定义的属性,就会报错找不到这个属性
- 设置 忽略 不存在的属性,两种写法都可以
// 设置 忽略 不存在的属性
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
- 在 fastjson 中,默认就会忽略这些不存在的 key
2.2 泛型的处理
@Data
public class ResultDTO<T> {
private Boolean success = Boolean.TRUE;
private T data;
private ResultDTO(){}
public static <T> ResultDTO<T> buildSuccess(T t) {
ResultDTO<T> result = new ResultDTO<>();
result.setData(t);
return result;
}
}
- 输出经过泛型处理的结果和泛型里的 Person 对象
/**
* 泛型的处理
*/
@Test
public void test3() throws JsonProcessingException {
Person person = new Person();
person.setName("xdr");
person.setAddress("深圳");
ResultDTO<Person> personResultDTO = ResultDTO.buildSuccess(person);
String s = objectMapper.writeValueAsString(personResultDTO);
// 反序列化为 ResultDTO<Person>
ResultDTO<Person> dataResult = objectMapper.readValue(s, new TypeReference<ResultDTO<Person>>() {
});
System.out.println("dataResult: " + dataResult);
System.out.println("data: " + dataResult.getData()); // 输出里面的 Person
}
3. 通用配置
- 指序列化或反序列化的时候都可以使用
3.1 驼峰转下划线和下划线转驼峰
- 全局配置:
1、序列化:驼峰转下划线
// 驼峰转下划线 userName -> user_name
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
/**
* 序列化
*/
@Test
public void test1() throws JsonProcessingException {
Person person = new Person();
person.setId(1);
person.setName("兮动人");
person.setAge(20);
person.setBirthDate(new Date());
person.setAddress("深圳市");
person.setRegisterDate(LocalDateTime.now());
String s = objectMapper.writeValueAsString(person);
System.out.println(s);
}
2、反序列化:下划线转驼峰
/**
* 反序列化
*/
@Test
public void test2() throws JsonProcessingException {
String str = "{\n" +
" \"id\" : 1,\n" +
" \"name\" : \"兮动人\",\n" +
" \"age\" : 20,\n" +
" \"address\" : \"深圳市\",\n" +
" \"flag\" : false,\n" +
" \"birth_date\" : \"2022-10-18 20:01:32\",\n" +
" \"register_date\" : \"2022-10-18 20:01:32\"\n" +
"}\n";
Person person = objectMapper.readValue(str, Person.class);
System.out.println(person);
}
3.2 指定属性名和JSON字符串中Key对应的关系
- 指定属性名,相当于给属性别名
- 序列化输出后,就是指定的别名
- 把上面JSON字符串反序列化后,输出的就是对应的 address 属性值
3.3 忽略指定属性
- 忽略 age 属性,默认为 true
- 序列化后就没有这个值输出了
- 反序列后即便传了 age 属性,也不会进行赋值处理
4. 利用 Jackson 做对象的更新
- 对象更新:对象的合并/重写,如果后者的对象有值,则用后者的,否则前者的值不变
/**
* 对象的更新
*/
@Test
public void test4() throws JsonMappingException {
Person person1 = new Person();
person1.setId(22);
person1.setName("xdr");
person1.setAddress("深圳 ");
Person person2 = new Person();
person2.setId(33);
Person person = objectMapper.updateValue(person1, person2);
System.out.println(person);
}