Jackson 2.x 系列【3】解析器 JsonParser

有道无术,术尚可求,有术无道,止于术。

本系列Jackson 版本 2.17.0

源码地址:https://gitee.com/pearl-organization/study-seata-demo

文章目录

    • 1. 前言
    • 2. 解析原理
    • 3. 案例演示
      • 3.1 创建 JsonParser
      • 3.2 解析
      • 3.3 读取
      • 3.4 测试

1. 前言

在上一篇文档中,我们使用JsonGenerator生成了一个JSON文件,接下来我们学习使用JsonParser进行解析。

2. 解析原理

JsonParser进行解析的大致流程如下:

  1. 从头开始扫描JSON字符串
  2. 依次识别每个JSON组成元素
  3. 解析到结束位置,关闭解析器

在这里插入图片描述
JSON格式是非常标准的,JsonParser会从头到尾识别每一个组成元素,比如识别到对象开始符号{时,会生成一个对应JsonToken令牌对象,其中包含了元素标识START_OBJECT

JsonToken对象是一个枚举类,用于判断解析元素的类型:

public enum JsonToken {// 当前无法返回NOT_AVAILABLE((String)null, -1),// 对象开始符号:{START_OBJECT("{", 1),// 对象结束符号:}END_OBJECT("}", 2),// 数组开始符号START_ARRAY("[", 3),// 数组结束符号END_ARRAY("]", 4),// 当时是属性名称FIELD_NAME((String)null, 5),// 嵌入对象VALUE_EMBEDDED_OBJECT((String)null, 12),// 字符串类型值VALUE_STRING((String)null, 6),// INT类型值VALUE_NUMBER_INT((String)null, 7),// FLOAT类型值VALUE_NUMBER_FLOAT((String)null, 8),// True 类型值VALUE_TRUE("true", 9),// False 类型值VALUE_FALSE("false", 10),// null 值VALUE_NULL("null", 11);
}

3. 案例演示

演示需求: 将之前生成的JSON文件反序列化为User对象。

3.1 创建 JsonParser

JsonParser是读取JSON内容API的基类,它有很多实现子类:
在这里插入图片描述
其实例也是由JsonFactory创建,JsonFactory提供了多种创建方法:

    public abstract JsonParser createParser(byte[] data) throws IOException;public abstract JsonParser createParser(byte[] data, int offset, int len) throws IOException;public abstract JsonParser createParser(char[] content) throws IOException;public abstract JsonParser createParser(char[] content, int offset, int len) throws IOException;public abstract JsonParser createParser(DataInput in) throws IOException;public abstract JsonParser createParser(File f) throws IOException;public abstract JsonParser createParser(InputStream in) throws IOException;public abstract JsonParser createParser(Reader r) throws IOException;public abstract JsonParser createParser(String content) throws IOException;public abstract JsonParser createParser(URL url) throws IOException;

这里我们直接通过文件对象创建:

        // 1. 创建 JsonParserJsonFactory jsonFactory = JsonFactory.builder().build();File file = new File("E:\\TD\\pearl\\study-jackson-demo\\jackson-core-demo\\src\\main\\java\\com\\pearl\\jacksoncore\\demo\\file\\user.json");JsonParser jsonParser = jsonFactory.createParser(file);

上面创建的JsonParser 实例类型是UTF8StreamJsonParser
在这里插入图片描述

3.2 解析

JsonParser提供了isClosed()方法判断是否关闭,nextToken()方法解析下一个元素,使用这两个方法循环解析JSON的所有元素:

        while (!jsonParser.isClosed()) {JsonToken jsonToken = jsonParser.nextToken();System.out.println("当前解析到的令牌类型:" + jsonToken);}

所有元素类型如下:

当前解析到的令牌类型:START_OBJECT
当前解析到的令牌类型:FIELD_NAME
当前解析到的令牌类型:VALUE_NUMBER_INT
当前解析到的令牌类型:FIELD_NAME
当前解析到的令牌类型:VALUE_STRING
当前解析到的令牌类型:FIELD_NAME
当前解析到的令牌类型:VALUE_NUMBER_INT
当前解析到的令牌类型:FIELD_NAME
当前解析到的令牌类型:START_OBJECT
当前解析到的令牌类型:FIELD_NAME
当前解析到的令牌类型:VALUE_NUMBER_INT

3.3 读取

JsonParser提供了多个将JSON解析为对象或树模型的方法:
在这里插入图片描述
查看readValueAs方法,可以看到实际是调用ObjectCodec对象的读取方法:

    public <T> T readValueAs(Class<T> valueType) throws IOException {return this._codec().readValue(this, valueType);}protected ObjectCodec _codec() {ObjectCodec c = this.getCodec();if (c == null) {throw new IllegalStateException("No ObjectCodec defined for parser, needed for deserialization");} else {return c;}}

ObjectCodec是一个抽象类,定义了JsonParserJsonGenerator用于序列化和反序列化POJO对象的正则表达式,其标准实现为jackson-databind模块中的ObjectMapper类。ObjectCodec是非常重要的一个类,JSONPOJO转换的规则和逻辑需要实现该抽象类。

ObjectCodec中可以看到定义了很多读写方法,同时它继承了TreeCodec抽象类,说明也具备读取为树模型的能力:

public abstract class ObjectCodec extends TreeCodec implements Versioned {public abstract Version version();public abstract <T> T readValue(JsonParser var1, Class<T> var2) throws IOException;public abstract <T> T readValue(JsonParser var1, TypeReference<T> var2) throws IOException;public abstract <T> T readValue(JsonParser var1, ResolvedType var2) throws IOException;public abstract <T> Iterator<T> readValues(JsonParser var1, Class<T> var2) throws IOException;public abstract <T> Iterator<T> readValues(JsonParser var1, TypeReference<T> var2) throws IOException;public abstract <T> Iterator<T> readValues(JsonParser var1, ResolvedType var2) throws IOException;public abstract void writeValue(JsonGenerator var1, Object var2) throws IOException;public abstract <T extends TreeNode> T readTree(JsonParser var1) throws IOException;public abstract void writeTree(JsonGenerator var1, TreeNode var2) throws IOException;public abstract TreeNode createObjectNode();public abstract TreeNode createArrayNode();public abstract JsonParser treeAsTokens(TreeNode var1);public abstract <T> T treeToValue(TreeNode var1, Class<T> var2) throws JsonProcessingException;/** @deprecated */@Deprecatedpublic JsonFactory getJsonFactory() {return this.getFactory();}public JsonFactory getFactory() {return this.getJsonFactory();}
}

我们自定义一个StudyObjectCodec,这里只实现readValue(JsonParser jsonParser, Class<T> aClass)方法,也只解析了User的几个属性,因为解析比生成复杂的多,这里只是简单演示:

public class StudyObjectCodec extends ObjectCodec {// 省略其他实现@Overridepublic <T> T readValue(JsonParser jsonParser, Class<T> aClass) throws IOException {// 1. 创建用户对象User user = new User();// 2. 循环解析每一个元素while (!jsonParser.isClosed()) {// 解析到下一个元素JsonToken jsonToken = jsonParser.nextToken();System.out.println("当前解析到的令牌类型:" + jsonToken);// 2.1 如果是属性名称类型if (JsonToken.FIELD_NAME.equals(jsonToken)) {String currentName = jsonParser.currentName(); // 获取属性名System.out.println("属性名称:" + currentName);if ("id".equals(currentName) ) {jsonParser.nextToken(); // 解析到下一个元素,即为属性对应的值Long userId = jsonParser.getLongValue();user.setId(userId);}if ("name".equals(currentName)) {jsonParser.nextToken();String userName = jsonParser.getValueAsString();user.setName(userName);}if ("age".equals(currentName)) {jsonParser.nextToken();int age = jsonParser.getIntValue();user.setAge(age);}}}// 3. 返回return (T) user;}

最后设置ObjectCodec,完整代码如下:

public class JsonParserDemo {public static void main(String[] args) throws IOException {// 1. 创建 JsonParserJsonFactory jsonFactory = JsonFactory.builder().build();File file = new File("E:\\TD\\pearl\\study-jackson-demo\\jackson-core-demo\\src\\main\\java\\com\\pearl\\jacksoncore\\demo\\file\\user.json");JsonParser jsonParser = jsonFactory.createParser(file);// 2. 反序列化 jsonParser.setCodec(new StudyObjectCodec());User user = jsonParser.readValueAs(User.class);System.out.println(user);}
}

3.4 测试

运行测试案例,查看控制台:

User{id=1701893746586685440, name='坤坤', age=18, org=null, roleList=null}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/280508.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言 指针练习

一、 a、b是两个浮点型变量&#xff0c;给a、b赋值&#xff0c;建立两个指针分别指向a的地址和b的地址&#xff0c;输出两个指针的值。 #include<stdio.h> int main() {float a,b,*p1,*p2;a10.2;b2.3;p1&a;p2&b;printf("a%f,b%f\n",a,b);printf("…

U-Net代码复现--更新中

本文记录自己的学习过程&#xff0c;内容包括&#xff1a; 代码解读&#xff1a;Pytorch-UNet 深度学习编程基础&#xff1a;Pytorch-深度学习&#xff08;新手友好&#xff09; UNet论文解读&#xff1a;医学图像分割&#xff1a;U_Net 论文阅读 数据&#xff1a;https://hack…

Java与Go:指针

在计算机内存中&#xff0c;每个变量都有一个唯一的地址&#xff0c;指针就是用来保存这个地址的变量。通过指针&#xff0c;我们可以间接地访问和修改存储在该地址处的数据。今天我们来聊一聊Java和Go指针&#xff0c;预告一下&#xff0c;我们需要借助C语言做一些小小的比较。…

基于cnn深度学习的yolov5+pyqt+分类+resnet+骨龄检测系统

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 YOLOv5与骨龄识别 YOLOv5&a…

容器中的大模型(三)| 利用大语言模型:容器化高效地部署 PDF 解析器实践...

作者&#xff1a;宋文欣&#xff0c;智领云科技联合创始人兼CTO 01 简介 大语言模型&#xff08;LLMs&#xff09;正逐渐成为人工智能领域的一颗璀璨明星&#xff0c;它们的强大之处在于能够理解和生成自然语言&#xff0c;为各种应用提供了无限可能。为了让这些模型更好地服务…

网络编程:数据库

一、作业 1> 创建一个工人信息库&#xff0c;包含工号&#xff08;主键&#xff09;、姓名、年龄、薪资。 2> 添加三条工人信息&#xff08;可以完整信息&#xff0c;也可以非完整信息&#xff09; 3> 修改某一个工人的薪资&#xff08;确定的一个&#xff09; 4> …

[C++]20:unorderedset和unorderedmap结构和封装。

unorderedset和unorderedmap结构和封装 一.哈希表&#xff1a;1.直接定址法&#xff1a;2.闭散列的开放定址法&#xff1a;1.基本结构&#xff1a;2.insert3.find4.erase5.补充&#xff1a;6.pair<k,v> k的数据类型&#xff1a; 3.开散列的拉链法/哈希桶&#xff1a;1.基…

【计算机网络】计算机网络概述

文章目录 一、计算机网络的概念二、 计算机网络的功能1. 数据通信2. 资源共享3. 分布式处理4. 提高可靠性5. 负载均衡 补充&#xff1a; 计算机的发展阶段小结三、计算机网络的组成1. 组成部分2. 工作方式3. 功能组成 四、 计算机网络的分类1. 按分布范围2. 按使用者3. 按交换技…

零拷贝原理+kafka中的零拷贝

零拷贝原理kafka中的零拷贝 kafka性能之零拷贝传统IO零拷贝mmp优化sendfile优化sendfile DMA scatter/gather优化Kafka是怎么使用零拷贝的 kafka性能之零拷贝 kafka中的零拷贝并不是说完全避免了上下文切换与cpu拷贝的次数, 而是减少这种拷贝次数 传统IO 传统的一次IO流程 rea…

学习开发小程序的起航日记

2024年3月16日 不知不觉中三月份还只剩了一半的光景&#xff0c;我想写的内容还很多没有写&#xff0c;或者更应该说&#xff0c;是想积累的还有很多。现在最应该去完善Java的内容&#xff0c;可还是想先等等。想等搞清楚小程序部分&#xff0c;想等积累完小程序的内容。 这几…

华为综合案例-普通WLAN全覆盖配置(2)

组网图 结果验证 在AC_1和AC_2上执行display ap all命令&#xff0c;检查当前AP的状态&#xff0c;显示以下信息表示AP上线成功。[AC_1] display ap all Total AP information: nor : normal [1] ExtraInfo : Extra information P : insufficient power supply ---…

冒泡排序的原理及其实现

✨✨✨学习的道路很枯燥&#xff0c;希望我们能并肩走下来! 目录 前言 一、冒泡排序的原理 二、代码实现 总结 前言 本篇详细介绍了冒泡排序的原理及其实现&#xff0c;让使用者对冒泡排序的原理及其实现有进一步认识&#xff0c;而不是仅仅停留在表面&#xff0c;更好的模…

xercesc库保存XML功能实现

目录 一 参考链接 二 运行结果 三 代码 一 参考链接 DOM Programming Guide (apache.org) Xerces-c DOM XML文件的构造_xerces-c domimplementation-CSDN博客 Xerces-c库的使用-CSDN博客 二 运行结果 三 代码 #if 1//参考链接&#xff1a; https://blog.csdn.net/RGBMa…

流畅的 Python 第二版(GPT 重译)(九)

第四部分&#xff1a;控制流 第十七章&#xff1a;迭代器、生成器和经典协程 当我在我的程序中看到模式时&#xff0c;我认为这是一个麻烦的迹象。程序的形状应该只反映它需要解决的问题。代码中的任何其他规律性对我来说都是一个迹象&#xff0c;至少对我来说&#xff0c;这表…

【数据可视化】Echarts中的其它图表

个人主页 &#xff1a; zxctscl 如有转载请先通知 文章目录 1. 前言2. 绘制散点图2.1 绘制基本散点图2.2 绘制两个序列的散点图2.3 绘制带涟漪特效的散点图 3. 绘制气泡图3.1 绘制标准气泡图3.2 绘制各国人均寿命与GDP气泡图3.3 绘制城市A、城市B、城市C三个城市空气污染指数气…

Tech Talks技术讲座中文培训-报名学习LPWAN、Matter、蓝牙和Wi-Fi最新开发技能!

Silicon Labs&#xff08;亦称“芯科科技”&#xff09;主办新一轮2024年“亚太区Tech Talks在线技术讲座”即将在5月9日至8月8日&#xff08;中文系列场次&#xff09;&#xff0c;以及4月24日至8月7日&#xff08;英文系列场次&#xff09;正式展开&#xff0c;现正热烈报名中…

uniapp使用Canvas给图片加水印把临时文件上传到服务器

生成的临时路径是没有完整的路径没办法上传到服务器 16:37:40.993 添加水印后的路径, _doc/uniapp_temp_1710923708347/canvas/17109238597881.png 16:37:41.041 添加水印后的完整路径, file://storage/emulated/0/Android/data/com.jingruan.zjd/apps/__UNI__BE4B000/doc/…

ES 常见面试题及答案

目录 es 写入数据流程 es 删除数据流程 es 读数据流程 es 部署的服务有哪些角色 es 的实现原理 es 和lucence 关系 如何提高写入效率 提高搜索效率 es doc value指的啥 分片指的啥&#xff0c;定义后可不可义再修改 深分页如何优化 对于聚合操作是如何优化的 元数据…

adobe animate 时间轴找不到编辑多个帧按钮

如题&#xff0c;找了半天&#xff0c;在时间轴上找不到编辑多个帧按钮,导致无法批量处理帧 然后搜索发现原来是有些版本被隐藏了&#xff0c;需要再设置一下 勾选上就好了

POI和EasyExcel区别和操作Excel

POI和EasyExcel操作Excel 常用场景 1、将用户信息导出为excel表格&#xff08;导出数据… &#xff09; 2、将Excel表中的信息录入到网站数据库&#xff08;文件数据上传… &#xff09; 开发中经常会设计到excel的处理&#xff0c;如导出Excel&#xff0c;导入Excel到数据库…