7. Jackson用树模型处理JSON是必备技能,不信你看(上)

简介: 7. Jackson用树模型处理JSON是必备技能,不信你看(上)

前言


你好,我是YourBatman。


上篇文章 体验了一把ObjectMapper在数据绑定方面的应用,用起来还是蛮方便的有木有,为啥不少人说它难用呢,着实费解。我群里问了问,主要原因是它不是静态方法调用,并且方法名取得不那么见名之意…


虽然ObjectMapper在数据绑定上既可以处理简单类型(如Integer、List、Map等),也能处理完全类型(如POJO),看似无所不能。但是,若有如下场景它依旧不太好实现:


  1. 硕大的JSON串中我只想要某一个(某几个)属性的值而已
  2. 临时使用,我并不想创建一个POJO与之对应,只想直接使用值即可(类型转换什么的我自己来就好)
  3. 数据结构高度动态化


为了解决这些问题,Jackson提供了强大的树模型 API供以使用,这也就是本文的主要的内容。


小贴士:树模型虽然是jackson-core模块里定义的,但是是由jackson-databind高级模块提供的实现


版本约定


  • Jackson版本:2.11.0
  • Spring Framework版本:5.2.6.RELEASE
  • Spring Boot版本:2.3.0.RELEASE


正文



树模型可能比数据绑定更方便,更灵活。特别是在结构高度动态或者不能很好地映射到Java类的情况下,它就显得更有价值了。


树模型


树模型是JSON数据内存树的表示形式,这是最灵活的方法,它就类似于XML的DOM解析器。Jackson提供了树模型API来生成和解析 JSON串,主要用到如下三个核心类:


  • JsonNodeFactory:顾名思义,用来构造各种JsonNode节点的工厂。例如对象节点ObjectNode、数组节点ArrayNode等等
  • JsonNode:表示json节点。可以往里面塞值,从而最终构造出一颗json树
  • ObjectMapper:实现JsonNode和JSON字符串的互转


这里有个萌新的概念:JsonNode。它贯穿于整个树模型中,所以有必要先来认识它。


JsonNode


JSON节点,可类比XML的DOM树节点结构来辅助理解。JsonNode是所有JSON节点的基类,它是一个抽象类,它有一个较大的特点:绝大多数的get方法均放在了此抽象类里(即使它没有实现),目的是:在不进行类型强制转换的情况下遍历结构。但是,大多数的修改方法都必须通过特定的子类类型去调用,这其实是合理的。因为在构建/修改某个Node节点时,类型类型信息一般是明确的,而在读取Node节点时大多数时候并不 太关心节点类型。


多个JsonNode节点构成Jackson实现的JSON树模型的基础,它是流式API中com.fasterxml.jackson.core.TreeNode接口的实现,同时它还实现了Iterable迭代器接口。


public abstract class JsonNode extends JsonSerializable.Base 
  implements TreeNode, Iterable<JsonNode> {
  ...
}


JsonNode的继承图谱如下(部分):


image.png


一目了然了吧,基本上每个数据类型都会有一个JsonNode的实现类型对应。譬如数组节点ArrayNode、数字节点NumericNode等等。


一般情况下,我们并不需要通过new关键字去构建一个JsonNode实例,而是借助JsonNodeFactory工厂来做。


JsonNodeFactory




构建JsonNode工厂类。话不多说,用几个例子跑一跑。


值类型节点(ValueNode)


此类节点均为ValueNode的子类,特点是:一个节点表示一个值。


@Test
public void test1() {
    JsonNodeFactory factory = JsonNodeFactory.instance;
    System.out.println("------ValueNode值节点示例------");
    // 数字节点
    JsonNode node = factory.numberNode(1);
    System.out.println(node.isNumber() + ":" + node.intValue());
    // null节点
    node = factory.nullNode();
    System.out.println(node.isNull() + ":" + node.asText());
    // missing节点
    node = factory.missingNode();
    System.out.println(node.isMissingNode() + "_" + node.asText());
    // POJONode节点
    node = factory.pojoNode(new Person("YourBatman", 18));
    System.out.println(node.isPojo() + ":" + node.asText());
    System.out.println("---" + node.isValueNode() + "---");
}



容器类型节点(ContainerNode)


此类节点均为ContainerNode的子类,特点是:本节点代表一个容器,里面可以装任何其它节点。


Java中容器有两种:Map和Collection。对应的Jackson也提供了两种容器节点用于表述此类数据结构:


  • ObjectNode:类比Map,采用K-V结构存储。比如一个JSON结构,根节点 就是一个ObjectNode
  • ArrayNode:类比Collection、数组。里面可以放置任何节点


下面用示例感受一下它们的使用:


@Test
public void test2() {
    JsonNodeFactory factory = JsonNodeFactory.instance;
    System.out.println("------构建一个JSON结构数据------");
    ObjectNode rootNode = factory.objectNode();
    // 添加普通值节点
    rootNode.put("zhName", "A哥"); // 效果完全同:rootNode.set("zhName", factory.textNode("A哥"))
    rootNode.put("enName", "YourBatman");
    rootNode.put("age", 18);
    // 添加数组容器节点
    ArrayNode arrayNode = factory.arrayNode();
    arrayNode.add("java")
            .add("javascript")
            .add("python");
    rootNode.set("languages", arrayNode);
    // 添加对象节点
    ObjectNode dogNode = factory.objectNode();
    dogNode.put("name", "大黄")
            .put("age", 3);
    rootNode.set("dog", dogNode);
    System.out.println(rootNode);
    System.out.println(rootNode.get("dog").get("name"));
}


运行程序,输出:


------构建一个JSON结构数据------
{"zhName":"A哥","enName":"YourBatman","age":18,"languages":["java","javascript","python"],"dog":{"name":"大黄","age":3}}
"大黄"


运行程序,输出:

------ValueNode值节点示例------
true:1
true:null
true_
true:Person(name=YourBatman, age=18)
---true---




相关文章
|
1月前
|
JSON JavaScript Java
在Java中处理JSON数据:Jackson与Gson库比较
本文介绍了JSON数据交换格式及其在Java中的应用,重点探讨了两个强大的JSON处理库——Jackson和Gson。文章详细讲解了Jackson库的核心功能,包括数据绑定、流式API和树模型,并通过示例演示了如何使用Jackson进行JSON解析和生成。最后,作者分享了一些实用的代码片段和使用技巧,帮助读者更好地理解和应用这些工具。
在Java中处理JSON数据:Jackson与Gson库比较
|
3月前
|
JSON C语言 数据格式
Python导出隐马尔科夫模型参数到JSON文件C语言读取
Python导出隐马尔科夫模型参数到JSON文件C语言读取
26 1
|
3月前
|
JSON Java API
Jackson:SpringBoot中的JSON王者,优雅掌控数据之道
【8月更文挑战第29天】在Java的广阔生态中,SpringBoot以其“约定优于配置”的理念,极大地简化了企业级应用的开发流程。而在SpringBoot处理HTTP请求与响应的过程中,JSON数据的序列化和反序列化是不可或缺的一环。在众多JSON处理库中,Jackson凭借其高效、灵活和强大的特性,成为了SpringBoot中处理JSON数据的首选。今天,就让我们一起深入探讨Jackson如何在SpringBoot中优雅地控制JSON数据。
130 0
|
5月前
|
JSON fastjson 数据格式
使用jackson和fastjson实现list与json互转
使用jackson和fastjson实现list与json互转
|
6月前
|
JSON 安全 JavaScript
Java一分钟之-JSON处理:Gson与Jackson库
本文对比介绍了Java中常用的两个JSON库Gson和Jackson。Gson以其简洁易用和自动序列化/反序列化功能受到青睐,而Jackson则以优异性能和丰富功能(如字段忽略、日期格式化)著称。文中通过代码示例展示了两者的基本用法,并讨论了常见问题及解决策略,包括时间格式处理、循环引用和类型匹配。在实际应用中,应根据性能需求、安全性和版本兼容性选择合适的库,并遵循最佳实践。
197 0
|
6月前
|
JSON fastjson Java
Spring Boot Jackson 和Fast JSON 用哪个好啊 ?
【4月更文挑战第22天】
1062 1
|
6月前
|
JSON Java Maven
使用Jackson进行 JSON 序列化和反序列化
使用Jackson进行 JSON 序列化和反序列化
135 0
|
1月前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
18天前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
22天前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。