0
点赞
收藏
分享

微信扫一扫

Jackson学习笔记

Jackson是当前用的比较广泛的,用来序列化和反序列化json的Java开源框架。Jackson社区相对比较活跃,更新速度也比较快, 从Github中的统计来看,Jackson是最流行的json解析器之一,Spring MVC的默认json解析器便是Jackson。

Java生态圈中有很多处理JSON和XML格式化的类库,Jackson是其中比较著名的一个。

Jackson是当前用的比较广泛的,用来序列化和反序列化json的Java开源框架。Jackson社区相对比较活跃,更新速度也比较快, 从Github中的统计来看,Jackson是最流行的json解析器之一,Spring MVC的默认json解析器便是Jackson。

Jackson学习笔记_序列化


url:​​https://mvnrepository.com/search?q=jackson​​

特性

● 性能且稳定:低内存占用,对大/小JSON串解析、大/小对象的序列化表现均很优秀。
● 流行度高:是很多流行框架的默认选择。
● 易使用:提供高层次的API,极大简化了日常使用的难度。
● 无需自己手动创建映射:内置了绝大部分序列化时和Java类型的映射关系。
● 干净的JSON:创建的JSON具有干净、紧凑、体积小等特点。
● 无三方依赖:仅依赖于JDK。
● 可扩展性强:与GSON等其他库相比的另一大特点是具有很强的可扩展性。
● Spring生态加持:jackson是Spring家族的默认JSON/XML解析器。

目前最新版本是2.11.4,Jackson 的核心模块由三部分组成:

● jackson-core 核心包,提供基于”流模式”解析的相关 API,它包括 JsonPaser 和 JsonGenerator。Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

● jackson-annotations 注解包,提供标准注解功能;

● jackson-databi 数据绑定包,提供基于”对象绑定” 解析的相关API( ObjectMapper)和”树模型” 解析的相关 API(JsonNode);基于”对象绑定” 解析的 API 和”树模型”解析的 API 依赖基于”流模式”解析的 API。

Maven引入

这里只引入核心包。

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.4</version>
</dependency>

Jackson注解

Jackson类库包含了很多注解,可以让我们快速建立Java类与JSON之间的关系。

1.属性命名

@JsonProperty注解指定一个属性用于JSON映射,默认情况下映射的JSON属性与注解的属性名称相同,不过可以使用该注解的value值修改JSON属性名,该注解还有一个index属性指定生成JSON属性的顺序,如果有必要的话。

2.属性包含

还有一些注解可以管理在映射JSON的时候包含或排除某些属性,下面介绍一下常用的几个。

①@JsonIgnore注解用于排除某个属性,这样该属性就不会被Jackson序列化和反序列化。
②@JsonIgnoreProperties注解是类注解。在序列化为JSON的时候,@JsonIgnoreProperties({"prop1", "prop2"})会忽略pro1和pro2两个属性。在从JSON反序列化为Java类的时候,@JsonIgnoreProperties(ignoreUnknown=true)会忽略所有没有Getter和Setter的属性。该注解在Java类和JSON不完全匹配的时候很有用。
③@JsonIgnoreType也是类注解,会排除所有指定类型的属性。

3.序列化相关

@JsonPropertyOrder和@JsonProperty的index属性类似,指定属性序列化时的顺序。
@JsonRootName注解用于指定JSON根属性的名称。

处理JSON

简单映射
我们用Lombok设置一个简单的Java类。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Friend {
private String nickname;
private int age;
}

然后就可以处理JSON数据了。首先需要一个ObjectMapper对象,序列化和反序列化都需要它。

ObjectMapper mapper = new ObjectMapper();
Friend friend = new Friend("yitian", 25);

// 写为字符串
String text = mapper.writeValueAsString(friend);
// 写为文件
mapper.writeValue(new File("friend.json"), friend);
// 写为字节流
byte[] bytes = mapper.writeValueAsBytes(friend);
System.out.println(text);
// 从字符串中读取
Friend newFriend = mapper.readValue(text, Friend.class);
// 从字节流中读取
newFriend = mapper.readValue(bytes, Friend.class);
// 从文件中读取
newFriend = mapper.readValue(new File("friend.json"), Friend.class);
System.out.println(newFriend);

程序结果如下。可以看到生成的JSON属性和Java类中定义的一致。

{"nickname":"yitian","age":25}
Friend(nickname=yitian, age=25)

集合的映射

除了使用Java类进行映射之外,我们还可以直接使用Map和List等Java集合组织JSON数据,在需要的时候可以使用readTree方法直接读取JSON中的某个属性值。需要注意的是从JSON转换为Map对象的时候,由于Java的类型擦除,所以类型需要我们手动用new TypeReference给出。

ObjectMapper mapper = new ObjectMapper();

Map<String, Object> map = new HashMap<>();
map.put("age", 25);
map.put("name", "yitian");
map.put("interests", new String[]{"pc games", "music"});

String text = mapper.writeValueAsString(map);
System.out.println(text);

Map<String, Object> map2 = mapper.readValue(text, new TypeReference<Map<String, Object>>() {
});
System.out.println(map2);

JsonNode root = mapper.readTree(text);
String name = root.get("name").asText();
int age = root.get("age").asInt();

System.out.println("name:" + name + " age:" + age);

程序结果如下:

{"name":"yitian","interests":["pc games","music"],"age":25}
{name=yitian, interests=[pc games, music], age=25}
name:yitian age:25

Jackson配置

Jackson预定义了一些配置,我们通过启用和禁用某些属性可以修改Jackson运行的某些行为。下面简单翻译一下Jackson README上列出的一些属性。

// 美化输出
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// 允许序列化空的POJO类
// (否则会抛出异常)
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
// 把java.util.Date, Calendar输出为数字(时间戳)
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

// 在遇到未知属性的时候不抛出异常
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 强制JSON 空字符串("")转换为null对象值:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

// 在JSON中允许C/C++ 样式的注释(非标准,默认禁用)
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
// 允许没有引号的字段名(非标准)
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
// 允许单引号(非标准)
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 强制转义非ASCII字符
mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
// 将内容包裹为一个JSON属性,属性名由@JsonRootName注解指定
mapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);

这里有三个方法,configure方法接受配置名和要设置的值,Jackson 2.5版本新加的enable和disable方法则直接启用和禁用相应属性,推荐使用后面两个方法。

个人实例

通过Python在某读书平台爬取了一些图书排行榜数据,并保存至MySQL。

Jackson学习笔记_json_02


新建webapp的Maven项目,此处省略Maven配置和Mybatis数据库相关配置和代码。

后端界面构造图书类。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
private int id;
private String title;
private String author;
private String percent;
private String prec;

@Override
public String toString() {
return "{id:" + id +
", name:'" + title + '\'' +
", author:'" + author + '\'' +
", percent:'" + percent + '\'' +
", pesc:'" + prec + '\''+"}";
}
}

调用test()方法,读取并生成booksList图书数据。

@WebServlet(name = "BooksServlet", value = "/BooksServlet")
public class BooksServlet extends HttpServlet {
List<Book> booksList = null;//设置全局变量
//读取数据库数据
public void test() {
SqlSession sqlSession = MybatisUtils.getSqlSession();
UseDao useDao = sqlSession.getMapper(UseDao.class);
// 查询数据库所有内容,这里的useDao是一个接口类
booksList = useDao.getUSerList();
// for (Book book : booksList) {
// System.out.println(book);
// }
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=gbk");
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
PrintWriter out = resp.getWriter();
//对 CORS 请求的响应缺少必需的Access-Control-Allow-Origin头,其用于确定在当前源内操作的资源是否可以访问。
//如果服务器在您的控制之下,请将请求站点的源添加到允许访问的域集,方法是将其添加到Access-Control-Allow-Origin头的值。
//当你自己电脑即是服务端又是客户端的时候可能就会遇到了,另外也还有其它方法可解决此问题。
resp.setHeader("Access-Control-Allow-Origin", "*");
ObjectMapper mapper = new ObjectMapper();
test();//调用方法读取图书列表数据生成booksList图书数据
String json = null;
try {
json = mapper.writeValueAsString(booksList);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
out.println(json);
out.flush();
out.close();
}

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=gbk");
doGet(req, resp);
}
}

前端简单代码实现。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>借书系统</title>
<script src="https://unpkg.com/axios/dist/axios.min.js"> </script>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="header">
<p>书籍是人类进步的阶梯!</p>
</div>
<div id="body">
<input type="button" value="加载" @click="books()">
<table>
<tr>
<td>序号</td>
<td>书名</td>
<td>作者</td>
<td>推荐值</td>
<td>描述</td>
</tr>
<tr v-for="book in booksList">
<td>{{book.id}}</td>
<td>{{book.title}}</td>
<td>{{book.author}}</td>
<td>{{book.percent}}</td>
<td>{{book.prec}}</td>
</tr>
</table>
</div>
<script>
var vm = new Vue({
el:'#body',
data:{
booksList:[],
},
// https://autumnfish.cn/search?keywords=%E6%9D%8E%E8%8D%A3%E6%B5%A9
methods:{
books:function(){
var that = this;
axios.get("http://localhost:8080/BooksServlet_war/BooksServlet").then(
function(response){
that.booksList = response.data;
}
)
},
}
})
</script>
</body>
</html>

当点击加载时,数据一下子全部显示,别提多开心了O(∩_∩)O哈哈~

Jackson学习笔记_json_03

成功拿到后台数据,太兴奋了,前端界面就没有认真去美化了。

Jackson学习笔记_json_04


虽然界面有点乱,但打开开发者模式时,就可以看到数据被解析成了Json格式,从而实现前端拿到后端的数据。

注意:这里的路径BooksServlet类似一个API接口。
刚开始学习这方面知识,目前水平就到这了,后面再努力学习一下如何去实现前后端数据交互。

箴言:因为这些东西是非常简单的。不要抱怨自己学不会,那是因为你没有足够用心。



举报

相关推荐

0 条评论