「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」。
作者:汤圆
个人博客:javalover.cc
前言
因为Jackson
是SpringBootStarter
自带的json
库,所以对Jackson
的学习还是很有必要的;
而在Jackson里,核心就是ObjectMapper
,它主要是负责序列化和反序列化Java对象;
目录
- 添加依赖
- 使用ObjectMapper
- 异常处理
正文
1. 添加依赖
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
复制代码
不出意外的话,一般都是用最新的版本,这里我们用的2.13.1;
这个依赖里面包含了jackson-core
和jackson-annotations
两个库,我们进到databind
依赖里面,就可以看到,如下所示:
<dependencies>
<!-- Builds on core streaming API; also needs core annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<!-- 06-Mar-2017, tatu: Although bom provides for dependencies, some legacy
usage seems to benefit from actually specifying version here in case
it is dependent on transitively
-->
<version>${jackson.version.annotations}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version.core}</version>
</dependency>
复制代码
2. 使用ObjectMapper
ObjectMapper
就是负责将对象的序列化和反序列化;
即将Java对象序列化为json字符串,和把json字符串解析为Java对象
2.1 序列化:
这里我们先定义一个Java对象User,如下所示:
@Data
public class User {
private String username;
private String password;
}
复制代码
然后我们创建一个User对象,并将其序列化为Json
字符串:
User user = new User("admin", "123");
ObjectMapper objectMapper = new ObjectMapper();
String str = objectMapper.writeValueAsString(user);
System.out.println(str);
复制代码
输出如下:
{"username":"admin","password":"123"}
复制代码
2.2 反序列化
就是将Json
字符串转为Java对象;
如果我们已知序列化时的对象类型,那么就可以直接将其解析为原有的类型;
如果不知道,也有其他的方式来解析,比如Map
或者JsonNode
;
解析为原来的Java类型:
这里我们直接用上面打印的json字符串 来处理:
User readValue = objectMapper.readValue(str, User.class);
System.out.println(readValue);
复制代码
输出如下:
User(username=admin, password=123)
复制代码
解析为JsonNode对象:
这里如果我们不知道Java对象的类型,可以用Jackson
内置的JsonNode对象,类似map:
JsonNode jsonNode = objectMapper.readTree(str);
String username = jsonNode.get("username").asText();
String password = jsonNode.get("password").asText();
System.out.println("username:"+username+", password:"+password);
复制代码
可以看到,这个JsonNode的操作跟Map很像,但是比Map灵活;包括获取值(可以通过索引来获取)、值的转型等,这里都给你封装好了;
解析为List集合:
如果需要解析的是一个json数组字符串,则需要用到TypeReference类;
这里我们创建一个json数组,然后将其序列化;
ArrayList<User> users = new ArrayList<>();
users.add(user);
users.add(user);
String jsonArrStr = objectMapper.writeValueAsString(users);
System.out.println(jsonArrStr);
List<User> userList = objectMapper.readValue(jsonArrStr, new TypeReference<List<User>>(){});
System.out.println(userList);
复制代码
这里用到了泛型的知识,可以参考Java中的泛型 - 细节篇 - 掘金 (juejin.cn)
3. 异常处理
有时候我们在解析Json字符串时,会附带一些多余的属性,此时ObjectMapper就会报错;
下面我们给上面的Json字符串增加一个属性email,然后将其解析为User对象:
String strNew = "{\"username\":\"admin\",\"password\":\"123\", \"email\": \"xxx.mail\"}";
User user1 = objectMapper.readValue(strNew, User.class);
System.out.println(user1);
复制代码
此时运行会报错,提示如下:
意思就是email属性无法解析,而且它还温馨提示了解决办法,就是可以将其标记为忽略属性;
下面我们就对ObjectMapper进行一个简单的配置,设置如下:解析未知的属性时是否报错,我们设置为否(默认true)
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
User user2 = objectMapper.readValue(strNew, User.class);
System.out.println(user2);
复制代码
此时运行就没问题了;
当然还有其他的很多配置,如下所示:
总结
本篇介绍了Jackson的基本知识,包括序列化和反序列化;
还介绍了一些异常处理的例子,比如解析未知的属性时不要报错,等等;