Jackson介绍
在Java中,万物皆对象,Jackson库就是一个基于Java语言开源的JSON格式解析工具
主要功能是提供JSON解析和生成,简单来说,Jackson就是用于将Java对象与JSON对象数据进行相互转换
- Jackson库的核心功能是将Java对象转为json字符串(序列化)以及将json字符串转为Java对象(反序列化)
- SpringMVC默认json解析器是Jackson
与其他json框架相比
- Jackson解析大的json文件速度较快
- Jackson运行时占用内存较低,性能比较好
- Jackson有灵活的API,可以很容易进行扩展和定制
核心模块
- jackson-core:核心包,提供基于“流模式”解析的相关API,生成和解析json
- jackson-annotations:注解包,提供标准注解功能
- jackson-databind:数据绑定包,提供基于“对象绑定”解析的相关API和“树模型”解析的相关API
其中,jackson-databind内部依赖了jackson-core和jackson-annotaions,所以只需导入jackson-databind即可
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.0</version>
</dependency>
基础序列化和反序列化
- ObjectMapper是Jackson序列化和反序列化的核心类,提供了许多用于定制序列化和反序列化的方法和配置选项
- 默认情况下,ObjectMapper在序列化对象时,将实体所有字段一一序列化,无论这些字段是否有值,是否为null
- 注意:如果实体的某个字段没有提供getter方法,则该字段不会被序列化
- ObjectMapper主要用于对Java对象进行序列化和反序列化
入门案例
@Test
public void test() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(20);
user.setBirthday(new Date());
user.setName("张三");
user.setAddress(null);
// 序列化
String jsonString = objectMapper.writeValueAsString(user);
System.out.println("序列化字符串:" + jsonString);
// 反序列化
User userFromJson = objectMapper.readValue(jsonString, User.class);
System.out.println("反序列化结果:" + userFromJson);
}
//序列化字符串:{"age":20,"name":"张三","birthday":1721266913536,"address":null}
//反序列化结果:User(age=20, name=张三, birthday=Thu Jul 18 09:41:53 CST 2024, address=null)
序列化API
String writeValueAsString(Object value):最常用
- 将任何Java对象,如POJO、List、Set、Map等序列化为json字符串
- 如果对象中某个属性的值为null,则默认也会序列化为null
- 如果value为null,返回序列化的结果也返回null
byte[] writeValueAsBytes(Object value)
- 将Java对象序列化为字节数组
writeValue(FIle resultFIle,Object value)
- 将Java对象序列化并输出指定文件中
writeValue(OutputStream out,Object value)
- 将Java对象序列化并输出到指定字节输出流中
@Test
public void test2() throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(20);
user.setBirthday(new Date());
user.setName("张三");
user.setAddress(null);
// 序列化byt
byte[] bytes = objectMapper.writeValueAsBytes(user);
System.out.println("序列化字节数组:" + new String(bytes));
// 序列化到文件
objectMapper.writeValue(new File("/Users/xuchang/Documents/json.txt"), user);
}
反序列化API
T readValue(String content, Class valueType)(最常用)
- 从给定的json字符串反序列化为Java对象
- valueType表示反序列化的任何Class对象(如 POJO、List、Set、Map等)
- content为空或者为null,都会报错
T readValue(byte[] src, Class valueType)
- 将json内容的字节数组反序列化为Java对象
T readValue(File src, Class valueType)
- 将本地json内容的文件反序列化为Java对象
T readValue(InputStream src, Class valueType)
- 将json内容的字节输入流反序列化为Java对象
T readValue(Reader src, Class valueType)
- 将json内容的字符输入流反序列化为Java对象
T readValue(URL src, Class valueType)
- 通过网络url地址将json内容反序列化为Java对象
常用配置
private static final ObjectMapper objectMapper;
static {
// 创建ObjectMapper对象
objectMapper = new ObjectMapper();
// configure方法 配置一些需要的参数
// 转换为格式化的json 显示出来的格式美化
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
// 序列化的时候序列对象的那些属性
// JsonInclude.Include.NON_DEFAULT 属性为默认值不序列化
// JsonInclude.Include.ALWAYS 所有属性
// JsonInclude.Include.NON_EMPTY 属性为 空(“”) 或者为 NULL 都不序列化
// JsonInclude.Include.NON_NULL 属性为NULL 不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
// 反序列化时,遇到未知属性会不会报错
// true - 遇到没有的属性就报错
// false - 没有的属性不会管,不会报错
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 如果是空对象的时候,不抛异常
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 忽略 transient 修饰的属性
objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true);
// 去除默认时间戳格式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 设置为中国北京时区
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
// 序列化日期格式 Date类型格式化
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
// 处理java8不同时间类型
JavaTimeModule module = new JavaTimeModule();
module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(("HH:mm:ss"))));
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss")));
// 序列换成json时,将所有的long变成string(因为js中得数字类型不能包含所有的java long值)
module.addSerializer(Long.TYPE, ToStringSerializer.instance);
module.addSerializer(Long.class, ToStringSerializer.instance);
objectMapper.registerModule(module);
}
@Test
public void testObjectMapper() throws JsonProcessingException {
User user = new User();
user.setId(1770376103094779915L);
user.setAge(20);
user.setBirthday(new Date());
user.setName("张三");
user.setAddress(null);
user.setLocalDateTime(LocalDateTime.now());
// 序列化
String jsonString = objectMapper.writeValueAsString(user);
System.out.println("序列化字符串:" + jsonString);
// 注意这里添加不存在的属性hobby,反序列化不会报错
jsonString = "{\"id\":1770376103094779915,\"age\":20,\"name\":\"张三\",\"birthday\":\"2024-07-19 11:02:19\",\"hobby\":\"打篮球\"}";
// 反序列化
User userFromJson = objectMapper.readValue(jsonString, User.class);
System.out.println("反序列化结果:" + userFromJson);
}
@Data
public class User {
private Long id;
private Integer age;
private String name;
private Date birthday;
private String address;
private LocalDateTime localDateTime;
}
输出结果
序列化字符串:{
"id" : "1770376103094779915",
"age" : 20,
"name" : "张三",
"birthday" : "2024-07-19 14:27:48",
"localDateTime" : "2024-07-19 14:27:48"
}
反序列化结果:User(id=1770376103094779915, age=20, name=张三, birthday=Fri Jul 19 11:02:19 CST 2024, address=null, localDateTime=null)
常用注解
@JsonProperty
用于在Java对象的属性和json字段之间建立映射关系
- value:用于指定json属性的名称,当Java属性和json属性名称不一致时使用
- index:指示此属性的数字索引的属性
- access:用于指定该属性的访问方式
- JsonAccess.READ\_ONLY(只读-序列化可见)
- JsonAccess.WRITE\_ONLY(只写-反序列化可见)
- JsonAccess.READ\_WRITE(可读可写)
@Test
public void test3() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(18);
user.setName("张三");
user.setAddress("北京");
user.setBirthday(new Date());
// 序列化为json字符串
String jsonString = objectMapper.writeValueAsString(user);
System.out.println(jsonString);
// 反序列化为对象
String userJson = "{\"age\":18,\"user_address\":\"北京\",\"user_birthday\":1721309276459,\"user_name\":\"张三\"}";
User userValue = objectMapper.readValue(userJson, User.class);
System.out.println(userValue);
}
@Data
public class User {
@JsonProperty(index = 0)
private Integer age;
@JsonProperty(value = "user_name", access = JsonProperty.Access.READ_ONLY, index = 3)
private String name;
@JsonProperty(value = "user_birthday", access = JsonProperty.Access.WRITE_ONLY, index = 2)
private Date birthday;
@JsonProperty(value = "user_address", access = JsonProperty.Access.READ_WRITE, index = 1)
private String address;
}
输出结果
{"age":18,"user_address":"北京","user_name":"张三"}
User(age=18, name=null, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京)
- 序列化属性名称及value设置的名称
- 序列化根据index属性排序,反序列化还是类自上而下的顺序
- 只读属性可以序列化,只写属性可以反序列化(读和写是相对内存中对象来理解的)
@JsonAlias
- 在反序列化的时候可以让Bean的属性接收多个json字段的名称
@Test
public void test4() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
// 反序列化为对象
String userJson = "{\"age\":18,\"address\":\"北京\",\"birthday\":1721309276459,\"nick_name\":\"张三\"}";
User userValue = objectMapper.readValue(userJson, User.class);
System.out.println(userValue);
}
@Data
public class User {
private Integer age;
@JsonAlias(value = {"nick_name","vip_name"})
private String name;
private Date birthday;
private String address;
}
输出结果
User(age=18, name=张三, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京)
@JsonIgnore
- 序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响
- 一般标记在属性或者方法上,返回的json数据即不包含该属性
@Test
public void test5() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(18);
user.setName("张三");
user.setAddress("北京");
user.setBirthday(new Date());
// 序列化为json字符串
String jsonString = objectMapper.writeValueAsString(user);
System.out.println(jsonString);
// 反序列化为对象
String userJson = "{\"age\":18,\"address\":\"北京\",\"birthday\":1721309276459,\"name\":\"张三\"}";
User userValue = objectMapper.readValue(userJson, User.class);
System.out.println(userValue);
}
@Data
public class User {
@JsonIgnore
private Integer age;
@JsonIgnore
private String name;
private Date birthday;
private String address;
}
输出结果
{"birthday":1721310730459,"address":"北京"}
User(age=null, name=null, birthday=Thu Jul 18 21:27:56 CST 2024, address=北京)
@JsonIgnoreProperties
- 序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响
@Data
@JsonIgnoreProperties({"age", "name"})
public class User {
private Integer age;
private String name;
private Date birthday;
private String address;
}
@JsonFormat
时间格式化注解
- pattern: 表示日期的格式,比如:yyyy-MM-dd HH:mm:ss
timezone: 默认是GMT,中国需要GMT+8
- 中国时间(Asia/Shanghai) = 格林尼治时间(GMT)+ 8
- 格林尼治时间(GMT) = 世界协调时间(UTC) + 0
@Test
public void test6() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
User user = new User();
user.setAge(18);
user.setName("张三");
user.setAddress("北京");
user.setBirthday(new Date());
// 序列化为json字符串
String jsonString = objectMapper.writeValueAsString(user);
System.out.println(jsonString);
// 反序列化为对象
User userValue = objectMapper.readValue(jsonString, User.class);
System.out.println(userValue);
}
@Data
public class User {
private Integer age;
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date birthday;
private String address;
}
输出结果
{"age":18,"name":"张三","birthday":"2024-07-18 22:10:36","address":"北京"}
User(age=18, name=张三, birthday=Thu Jul 18 22:10:36 CST 2024, address=北京)
@JsonPropertyOrder
- 用于指定实体生成json时的属性顺序
// 自定义顺序
@JsonPropertyOrder({"name", "age", "address"})
//按字母排序
@JsonPropertyOrder(alphabetic=true)