XML与JSON 及其对应的Java包 Gson FastJson
4-8 XML与JSON
XML概述
- 可扩展标记语言:
- xml与平台无关,是一门独立的标记语言。与任何编程语言无关。
- xml具有自我描述性,能够清晰地展现其特性。
- xml数据不一定是文件形式存储,也可以在内存中构建xml数据。
- Java编程语言是为了解决人和机器的交流问题,而xml是为了解决程序与程序之间的交流问题。
- XML应用场景:
- 网络数据传输(不常用):
- 原始数据传输或者加特定字符分隔,可能带来各种问题,例如特定字符无法传输的问题。
- 虽然Java可以采用序列化的方式进行流传输,但是这并不适用于其他编程语言。
- 为了统一格式并且适配于更多情况下的数据格式表示,引入了XML和JSON的标记语言。
- 数据存储:(基本不用)
- 配置文件:(常用)XML适用于小数据的应用场景例如配置文件,当数据量很大时,使用JSON性能更高。
- 网络数据传输(不常用):
XML格式
自我描述部分,如版本和编码方式:
<?xml version="1.0" encoding="UTF-8"?> <!-- 注释不能写在文档文档声明前 -->
标记部分:用于表示数据使用的格式:
<!--标记 ( 元素 / 标签 / 节点) XML文档,由一个个的标记组成.语法:开始标记(开放标记): <标记名称>结束标记(闭合标记): </标记名称>标记名称: 自定义名称,必须遵循以下命名规则: 1.名称可以含字母、数字以及其他的字符 2.名称不能以数字或者标点符号开始 3.名称不能以字符 “xml”(或者 XML、Xml)开始 4.名称不能包含空格,不能包含冒号(:) 5.名称区分大小写标记内容: 开始标记与结束标记之间 ,是标记的内容.例如 ,我们通过标记, 描述一个人名:<name>李伟杰</name> 6.名称可以重名,包括同层名称也可以重复 -->
有且必须有仅有一个根标记:
<!--正确例子:--> <names><name>张三</name><name>李四</name> </names> <!--错误例子:两个根 <name>李四</name> <name>麻子</name> -->
标记可以嵌套,但不能交叉,即有层级关系。
<!--举一个反例:第二层中就没有层级关系,属于交叉关系 错误例子:存在交叉关系 <person><name>李四<age></name>18</age> </person> -->
标记除了开始和结束外,还可以有属性(同一个标签里<属性>的属性名不能重复):
<!--标记中的属性, 在标记开始时 描述, 由属性名和属性值 组成.格式:在开始标记中, 描述属性.可以包含0-n个属性, 每一个属性是一个键值对!属性名不允许重复 , 键与值之间使用等号连接, 多个属性之间使用空格分割.属性值 必须被引号引住.案例:--><persons><person id="10001" groupid="1"><name>李四</name><age>18</age></person><person id="10002" groupid="1"><name>李四</name><age>20</age></person></persons>
注释格式:
<!-- 注释不能写在文档文档声明前 注释不能嵌套注释格式:注释开始: “<!--”注释结束: 如下图标所示 -->
语法进阶
CDATA
(了解):其实就是提供了类似编程语言中的转义功能,将某个特殊字符转义为普通字符。
其底层逻辑是,xml解析器在碰到一定格式
<![CDATA[
开头和]]>
结束的符号时当成普通字符忽略。<names><name>张三<![CDATA[<name>李四</name>]]></name> </names>
命名空间(框架中才会使用):
- 引入的目的:XML命名空间提供避免元素命名冲突的方法。
- 本质问题:和Java中的package的概念是一样的。
- 基本格式:
特定的符号:你的前缀="你的命名空间地址"
Java操作XML(掌握)
两大解析方法:SAX解析和DOM解析
- SAX解析:
- 逐行读取解析,对空间的内存需求不大,解析完上一行再解析下一行。
- 每解析到一个标签就触发一次事件,如果已经得到需要的数据,就不必继续解析了。
- 解析方向是单向的,前面解析过的数据已经被释放无法获取。
- 无法获取层级关系,只能由程序员自己去维护。
- 只读解析方式,无法修改XML文档内容。
- DOM解析:
- 用于平台无关的方式表示XML文档,需要全部读取,对内存需求量大。
- 在内存中建立文档树模型,不再使用原XML文档,可以完成数据的读写。
- 由于实际应用场景中,xml文件很小,因此内存需求大的缺点也可以忽略。
- SAX解析:
基于DOM解析的另外两种方法:
- JDOM解析:为Java定制模型
- 大量使用了Java集合,方便Java开发。
- 使用具体类而不是接口,简化了DOM的API。
- 不是接口,灵活性也就降低了。
- DOM4J解析:
- 它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的
XPath
支持、XML Schema
支持以及用于大文档或流化文档的基于事件的处理。 - 它还提供了构建文档表示的选项,读取节点就想操作文件路径一样方便。
- 它是JDOM的一种智能分支。它合并了许多超出基本XML文档表示的功能,包括集成的
- JDOM解析:为Java定制模型
DOM4J解析(掌握)
首先导入
dom4j.jar
包。Node
接口的子孙:Document
和Element
SAXReader
用于从输入流(可以是文件或网络)中获取XML文档对象。返回的是一个Document
类型。Document
用于从文档中获取根元素对象和添加一个根元素节点。返回的是Element
类型。Element
用于操作具体的元素:包括获取/添加节点名称、内容、属性等等具体的应用核心代码:
/*** 从本地文件作为输入流获取*/ //1. 获取输入流 FileInputStream fis = new FileInputStream("c://Demo1.xml"); //2. 创建XML读取对象 SAXReader sr = new SAXReader(); //3. 读取并得到文档对象 Document doc = sr.read(fis); //4. 通过文档获取根元素 Element root = doc.getRootElement(); //5. 通过根节点获取元素集合 List<Element> es = root.elements(); for(int i=0;i<es.size();i++){Element book = es.get(i);System.out.println(book.attributeValue("id"));System.out.println(book.elementText("name"));System.out.println(book.elementText("info")); System.out.println(book.element("xiang").elementText("wei"));System.out.println("-----------------------------"); } /*** 从网络资源作为输入流获取*/ //1. 获取到XML资源的输入流 URL url = new URL("http://apis.juhe.cn/mobile/get?phone=18313935565&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253"); URLConnection conn = url.openConnection(); InputStream is = conn.getInputStream(); //2. 创建一个XML读取对象 SAXReader sr = new SAXReader(); //3. 通过读取对象 读取XML数据,并返回文档对象 Document doc = sr.read(is);
xPath
解析更加方便:路径表达式:
路径表达式:1. / : 从根节点开始查找2. // : 从发起查找的节点位置 查找后代节点 常用3. . : 查找当前节点4. .. : 查找父节点5. @ : 选择属性. 常用属性使用方式:[@属性名='值'][@属性名>'值'][@属性名<'值'][@属性名!='值'
前面获取文档对象操作类似,下面给出核心代码:
//1. 通过文档对象+xpath,查找所有的name节点 List<Node> names = doc.selectNodes("//book[@id='1001']//name"); for (int i=0;i<names.size();i++){System.out.println(names.get(i).getName());System.out.println(names.get(i).getText()); } //2. 通过文档对象+xpath,查找第一个name节点 Node n = doc.selectSingleNode("//book[@id='1002']//name"); System.out.println(n.getName()+":"+n.getText());
Java利用文档对象生成XML(熟悉)
需要借助文档帮助器这个类来创建空的文档对象。
有了文档对象,然后操作根节点,然后丰富子节点,这部分操作和解析类似,调用API即可。
最后需要把文档对象写入到文件输出流中,因此需要先创建一个文件输出流,并利用
XMLWriter
类写入文档对象到文件中。核心代码如下:
//1. 通过文档帮助器,创建一个文档对象 Document doc = DocumentHelper.createDocument(); //2. 给文档添加第一个节点(根节点) Element books = doc.addElement("books"); //3. 通过根节点, 丰富子节点 这里忽略 //4. 创建一个文件输出流 FileOutputStream fos = new FileOutputStream("c://books.xml"); //5. 将输出流转换为XML输出流 XMLWriter xw = new XMLWriter(fos); //6. 写出文档 xw.write(doc); //7. 释放资源 xw.close();
XStream
将Java对象生成XML(了解)最终生成的是一个字符串,核心代码如下:
Person p = new Person(); p.setName("张三"); p.setAge(18); //XStream使用 //1、创建XStream对象 XStream x = new XStream(); //2、修改某个类型生成的节点 (可选的,默认为包名.类名) x.alias("person",Person.class); //3、传入对象,开始生成 String xml = x.toXML(p); System.out.println(xml);
JSON
JSON:
JavaScript Object Notation
JS对象简谱 , 是一种轻量级的数据交换格式.一个对象, 由一个大括号表示:
括号中 描述对象的属性。通过键值对来描述对象的属性(可以理解为, 大括号中, 包含的是一个个的键值对)
格式注意事项:
键与值之间使用冒号连接, 多个键值对之间使用逗号分隔.
键值对的键应使用引号引住 (通常Java解析时, 键不使用引号会报错. 而JS能正确解析.)
键值对的值, 可以是JS中的任意类型的数据,考虑到其他语言兼容,常使用的有布尔类型、数字类型、字符串类型。
注意键值对中的值可以继续是一个对象或者一个数组。
举例说明:
{"name":"forwardxiang","age":18,"friends":["张三","李四","王二","麻子",{"name":"我就是我","info":"不一样的烟火"}],"history":{"school":"大学",}}
根据使用的编程语言去查询对应的
JSON库
,例如C/C++
语言常用的最简单的cJSON库
。Java
使用的谷歌的Gson
和阿里的FastJson
,可以从GitHub中下载最新的包。由于Java官方没有内置相关库,使用其他库可能带来漏洞危险。
Java对象和JSON字符串互转
经过实际调试发现:
Gson
与FastJson
库在JSON字符串转Java对象
有所区别,FastJson
库在使用JSON.parseObject
进行解析时会报JSONException: create instance error
错误,它要求指定要转换的类是public
的。Gson
常用API:/** * Java对象转JSON字符串 */ Book b = new Book("100","金苹果","种植苹果真辛苦"); String s = new Gson().toJson(b); System.out.println(s); /** * JSON字符串转Java对象 */ Book a = new Gson().fromJson(s, Book.class); System.out.println(a.getId());
FastJson
常用API:/** * Java对象转JSON字符串 */ Book book = new Book("100","金苹果","种植苹果真辛苦"); String jsons = JSON.toJSONString(book); System.out.println(jsons); /** * JSON字符串转Java对象 */ Book b = JSON.parseObject(jsons, Book.class); System.out.println(b.getId());
JSON字符串
转Java对象
时,可以指定转换的类型,因此可以指定转换为HashMap
集合,然后通过键名去获取各个键值。JSON数组
在Java
中对应一个ArrayList
集合,FastJson
中还特意提供了JSON.parseArray
方法用于单独解析数组。
我的疑问
FastJson
库在使用JSON.parseObject
进行解析时会报JSONException: create instance error
错误原因是什么?- 这个问题主要是因为Java内部类和嵌套类的实现机制造成的,首先按照Java编程思想的说法,静态的内部类叫做嵌套类,那么两者有什么区别呢?一般的内部类虽然在源代码中没有写,但是编译后会看到里面多了一个指向外部类的引用,如果使用内部类进行
json序列化
,会因为找不到它的外部类而报异常,而嵌套类因为是静态的,里面没有默认的外部类的引用,即使没有外部类的对象也能够使用,因此在json
转换的时候不会报错。
- 这个问题主要是因为Java内部类和嵌套类的实现机制造成的,首先按照Java编程思想的说法,静态的内部类叫做嵌套类,那么两者有什么区别呢?一般的内部类虽然在源代码中没有写,但是编译后会看到里面多了一个指向外部类的引用,如果使用内部类进行
XML与JSON 及其对应的Java包 Gson FastJson相关推荐
- kryo java_优化Java序列化– Java,XML,JSON,Kryo,POF
kryo java 也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,而且由于每个JDK似乎都比 ...
- 优化Java序列化– Java,XML,JSON,Kryo,POF
也许我很天真,但是我一直认为Java序列化肯定是将Java对象序列化为二进制形式的最快,最有效的方法. 毕竟Java是第7个主要发行版,所以这不是新技术,并且由于每个JDK似乎都比上一个快,因此我错误 ...
- saxon 使用_Java XML和JSON:Java SE的文档处理,第1部分:SAXON和Jackson
saxon 使用 XML和JSON对我来说很重要,我感谢Apress让我写了一整本有关它们的书. 在本文中,我将简要介绍新书的第二版Java XML和JSON . 如果有足够的空间,我还将展示两个有用 ...
- json:JSONObject包的具体使用(JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包)...
1.JSONObject介绍 JSONObject-lib包是一个beans,collections,maps,java arrays和xml和JSON互相转换的包. 2.下载jar包 http:// ...
- JAVA序列化标准格式(XML、JSON)
(一) 序列化:将java对象转换为字节序列的过程叫做序列化 反序列化:将字节对象转换为java对象的过程叫做反序列化 通常情况下,序列化有两种用途: 1) 把对象的字节序列永久的保存在硬盘中 2) ...
- JAVA工具方法 —— JSON转XML 和 XML转JSON
2019独角兽企业重金招聘Python工程师标准>>> 这阵子一直在做一个三方支付,数据传递用的都是xml 但是在项目里都是用的json,没办法 研究了下json和xml互转的方法 ...
- Java学习(第十二天)XML和JSON
XML和json XML:可扩展标记语言(eXtensible Markup Language) 特性: 1.xml具有平台无关性,是一门独立的标记语言 2.xml具有自主描述性 学习xml的理由: ...
- Java学习-11 XML与JSON
Java学习-11 XML与JSON 1.XML 1.1.简介 可扩展标记语言(eXtensible Markup Language). 特性:1. xml具有平台无关性, 是一门独立的标记语言.2. ...
- Java如何xml转json字符串_xml字符串转json字符串
XML字符串转JSON字符串网上的方法很多,这里主要推荐两种: 1.使用org.json包 jar地址:http://mvnrepository.com/artifact/org.json/json ...
最新文章
- windows7 端口查看以及杀死进程释放端口
- python给一列数据增加前缀_python自制工具----给文件添加前后缀。
- MaxCompute 多行数据合并为一行数据
- 精通mysql_《深入精通Mysql(五)》实战:Mysql实现主从复制
- MSRA的Transformer跨界超越CNN,还解决了计算复杂度难题
- 小程序工程化实践(上篇)-- 手把手教你撸一个小程序 webpack 插件,一个例子带你熟悉 webpack 工作流程...
- 在博客中如何让code具有比较易读的格式
- 美肤磨皮算法OpenCV3实现
- (SQL语句)按指定时间段分组统计
- java 开发人员工具_Java开发人员应该知道的7种新工具
- 做技术知道了哪些事情代表自己成熟了?
- 垃圾回收 | Java垃圾回收,这杯咖啡,不仅好喝,而且实用!
- node-gyp 出错
- 算法图解 各部分回忆
- sql 判断分钟是偶数数据_SQL注入数据库类型判断
- 简述static关键字、void与void *(void指针)、函数指针
- 删除root 家目录,及恢复方法
- Python人脸识别之——创建csv文件 create_csv.py 代码 Python3.7
- DICOM获取worklist患者列表抓包分析
- 深度学习花书+机器学习西瓜书电子版我找到了
热门文章
- 深蓝学院-视觉SLAM课程-第3讲笔记-李群和李代数
- 天空卫士C++ 一面(技术面、61min)
- ansible 修改文件变量_ansible学习心得
- Java实现 LeetCode 385 迷你语法分析器
- Origin软件的快捷键汇总及工具栏快速指引
- 【安信可PB-01/02模组专题③】ESP32-G WIFI蓝牙网关与PB02模组开发进行组网通讯
- 跨界储能领域 金冠股份签订7000万锂电池储能系统销售大单
- C 语言初学——一起分享、共同学习。
- 可解释的对抗训练网络模型:Interpreting Adversarially Trained Convolutional Neural Networks-ICML 2019
- 图数据库Neo4j学习笔记系列