Java中的XML&JSON相关的知识
注意:本内容的代码运行时需要导入三个jar文件
分别是:
xstream-1.3.1.jar
jaxen-1.1-beta-7.jar
dom4j-1.6.1.jar
同时,对其进行好配置,该步骤在本内容中以跳过
XML&JSON
XML
是一种可扩展标记语言,标准通用标记语言的子集
- 特性:
(1)具有平台无关性
(2)具有自我描述性 - 作用:
(1)网络数据传输
(2)数据存储
(3)配置文件
(4)共享数据
(5)从HTML中分离数据 - 语法格式
(1)声明语法: <?xml version="1.0" encoding="UTF-8"?> 我的文档中要把“UFT-8”中的-去掉才能通过编译,后边却出现中文的乱码
(2)标记语法(元素/便签/节点):
由一个个标记组成
开始标记:<标记名称>
结束标记:</标记名称>
(3)命名的原则:
1)名称可以含字母、数字以及其他的字符
2)名称不能以数字或者标点符号开始
3)名称不能以字符 “xml”(或者 XML、Xml)开始
4)名称不能包含空格,不能包含冒号(:)
5)名称区分大小写
开始标记与结束标记之间是标记内的内容
(4)注意事项:
1)一个XML文档中, 必须有且且仅允许有一个根标记
比如:
2)标记可以嵌套, 但是不允许交叉
比如:
3)标记的层级称呼 (子标记, 父标记 , 兄弟标记, 后代标记 ,祖先标记)
比如:
其中,number是book的子标记,也是book的后代标记,同时number也是book的后代标记,price是number的兄弟标记,book是price的父标记,books是price的祖先标记
4)标记名称是允许重复的
5)标记除了开始和结束 , 还有属性,而标记中的属性, 在标记开始时描述, 由属性名和属性值组成
格式
a.在开始标记中, 描述属性
b.可以包含0-n个属性,每一个属性是一个键值对
c.属性名不允许重复,键与值之间使用等号连接, 多个属性之间使用空格分割
d.属性值必须被引号引住
案例:
解析器
常见的四种:SAX、DOM、JDOM、DOM4J
(1)SAX:解析方式是事件驱动机制,通过SAX解析器逐行读取XML文件解析
1)优点:
a.分析能够立即开始,而不是等待所有的数据被处理
b.逐行加载,节省内存.有助于解析大于系统内存的文档
c.有时不必解析整个文档,它可以在某个条件得到满足时停止解析
2)缺点
a.单向解析,无法定位文档层次,无法同时访问同一文档的不同部分数据,由于是逐行解析,则在该行以前的行数内容读取完毕时会将前面的内容视为垃圾回收
b.无法得知事件发生时元素的层次, 只能自己维护节点的父/子关系
c.只读解析方式, 无法修改XML文档的内容
(2)DOM:是用与平台和语言无关的方式表示XML文档的官方W3C标准,在使用时,程序员可以通过操作文档树,来完成数据的获取、修改、删除等
1)优点
a.文档在内存中加载,允许对数据和结构做出更改
b.访问是双向的,可以在任何时候在树中双向解析数据
2)缺点
文档全部加载在内存中 , 消耗资源大
(3)JDOM:目的是成为Java特定文档模型,它简化与XML的交互并且比使用DOM实现更快
1)优点
a.使用具体类而不是接口,简化了DOM的API
b.大量使用了Java集合类,方便了Java开发人员
2)缺点
a.没有较好的灵活性
2)性能不是那么优异
解析时使用的接口及类
通过DOM4J的方式对文件进行解析,其中运用到dom4j、Document、Element、输入输出流等工具及方法
DOM4J解析的步骤:
(1)引入jar文件dom4j.jar
(2)创建一个指向XML文件的输入流
FileInputStream fis = new FileInputStream("文件的地址");
(3)创建一个用于XML读取的对象
SAXReader sr = new SAXReader();
(4)使用读取工具对象,读取XML文档的输入流,并得到对象
Document doc = sr.read(fis);
(5)通过文档对象,获取XML文档中的根元素
Element root = doc.getRootElement();
Document
加载到内存的整个XML文档
常用的方法:
方法 | 描述 |
---|---|
Element getRootElement() | 通过文档对象获取XML文档的根对象 |
Element addElement(String SonNodeName) | 添加根节点 |
Element
方法 | 描述 |
---|---|
String getName() | 获取节点名称 |
String getText() | 获取节点内容 |
String setName() | 设置节点内容 |
Element element(String FirstNodeName) | 根据节点名称获取匹配名称的第一个子节点 |
List<Element> elements() | 获取所有子节点的对象 |
String attributeValue(String PropertyName) | 获取节点的属性值 |
String elementText(String SonNodeName) | 获取子节点的内容 |
void addAttribute(String PropertyName,String Property) | 添加属性 |
举个例子
我们先下一个文本文件:
内容如下:
<?xml version="1.0" encoding="utf8"?>
<books>
<book number="01">
<name>123</name>
<price>29.5</price>
</book>
<book number="02">
<name>321</name>
<price>22.5</price>
</book>
</books>
我的文档中要把“UFT-8”中的-去掉才能通过编译,后边却出现中文的乱码,为了能够显示出来,所以我这里边就不出现中文的字段了
然后我们去将文件进行解析
步骤:
(1)通过文档的路径获取到输入流中
(2)创建一个XML的对象去读取并获得文档
(3)通过获取的文档读取出根文件
(4)对获取的根文件进行解析
package Demo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
public class Demo {
public static void main(String[] args) throws IOException, DocumentException {
//1.获取输入流
FileInputStream fis = new FileInputStream("c://Book.xml ");
//2.创建XMl的读取对象
SAXReader sr = new SAXReader();
//3.读取并获得文档文件
Document doc = sr.read(fis);
//4.通过文档获取根文件
Element root = doc.getRootElement();
//5.开始解析文件
System.out.println(root.getName());
Element book = root.element("book");
System.out.println(book.getName());
List<Element> es = root.elements();
for(int i=0;i<es.size();i++){
Element e = es.get(i);
System.out.println(e.elementText("name"));
System.out.println(e.elementText("price"));
}
fis.close();
}
}
让我们来看看运行结果
图中我们可以看出可以获取到子节点中的名称以及内容
注意:当解析的是网络的xml文件时,要先获取将其网址,并用URL进行接收:
获取xml资源的输入流:
URL url = new URL(“网络文件的地址”)
URlConnection uc = url.openConnection()
InputStream is = uc.getInputStream()
我们可以通过一个网址去进行测试:
http://apis.juhe.cn/mobile/get? phone=13590008168&dtype=xml&key=9f3923e8f87f1ea50ed4ec8c39cc9253
这是一个通过电话号码获取信息的网址,以XML的格式显示
其中内部的“13590008168”是一个电话号码,你们可以修改成其他的电话号码
获取到的信息如下:
<root>
<resultcode>200</resultcode>
<reason>Return Successd!</reason>
<result>
<province>广东</province>
<city>湛江</city>
<areacode>0759</areacode>
<zip>524000</zip>
<company>移动</company>
<card/>
</result>
<error_code>0</error_code>
</root>
接下来就让我们进行获取XML文件并对其进行解析:
其中,我们做一判断,当所在地和城市是一样的时候,只输出城市而两者不同时,则输出所在地和城市
package Demo;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
public class Demo2 {
public static void main(String[] args) throws IOException, DocumentException {
String phone = "13590008168";
//1.获取XML资源对象的输入流
URL url = new URL("http://apis.juhe.cn/mobile/get? phone="+phone+"&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);
//4.获取根节点
Element root = doc.getRootElement();
//5.解析内容
String code = root.elementText("resultcode");
if("200".equals(code)){
Element result = root.element("result");
String prov = result.elementText("province");
String city = result.elementText("city");
if(prov.equals(city)){
System.out.println("手机的归属地为:" + city);
}else {
System.out.println("你的手机号是:" + phone);
System.out.println("手机的归属地为:" + prov + " " + city);
}
}else {
System.out.println("请输入正确的手机号");
}
}
}
接下来让我们看看运行结果
我们换个号码:18819773653再来试试
利用Java生成XML文档
涉及使用的方法
方法 | 描述 |
---|---|
Document createDocument() | 创建一个Document的文件对象 |
Element addElement(String SonNodeName) | 添加根节点 |
FileOutputStream(String Path) | 输出流的构造方法,Path是为需要存储的文件路径 |
XMLWriter(FileOutputStream fileoutputstream) | XML文档输出流的构造方法,将输出流中的内容生成XML文件 |
void XMLWrite(FileOutputStream fileoutputstream) | 作为XML文档写入输出流 |
void close() | 关闭流的方法 |
生成步骤:
(1)通过文档帮助器创建一个空的文档对象
(2) 利用文档对象向内部添加根节点以及多次输入进行丰富
(3)创建用于存储文件的文件输出流,最后将其转换成XML文档
JSON
是一种轻量级的数据交换格式
格式:
①对象格式:一个对象, 由一个大括号表示. 括号中 描述对象的属性 . 通过键值对来描述对象的属性 (可以理解为, 大括号中, 包含的是一个个的键值对.)
1)键与值之间使用冒号连接, 多个键值对之间使用逗号分隔.
2)键值对的键 应使用引号引住 (通常Java解析时, 键不使用引号会报错. 而JS能正确解析)
3)键值对的值, 可以是JS中的任意类型的数据
例子:比如我们要写一个Book的对象其中包含有number和price属性
{
"number":123,
"price":25
}
②数组格式:在JSON格式中可以与对象互相嵌套
[元素1,元素2…]
例子:比如我们要写一个Book的对象,其中包含有sell方法,又有number和price属性,而price属性中包含有四个内容
{
"number":123,
"price":["春季卖价","夏季卖价","秋季卖价","冬季卖价"]
"sell":{
“无法售卖”
}
}
我们来举个例子实行一下生成XML文档
package Demo;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.XMLWriter;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo3 {
public static void main(String[] args) throws IOException {
//1.通过文档帮助器,创建空的文档对象
Document doc = DocumentHelper.createDocument();
//2.向文档对象中,加入根节点对象
Element books = doc.addElement("books");
//3.向根节点中添加元素丰富子节点
for(int i=1;i<=3;i++){
Element book = books.addElement("book");
book.addAttribute("number", String.valueOf(i));
Element name = book.addElement("name");
Element price = book.addElement("price");
name.setText(String.valueOf(123+i));
price.setText(String.valueOf(56+10*i));
}
//4.创建文件输出流
FileOutputStream fos = new FileOutputStream("c:\\MyBooks.xml");
//5. 将文件输出流 , 转换为XML文档输出流
XMLWriter xw = new XMLWriter(fos);
// 6. 写出XML文档
xw.write(doc);
// 7. 释放资源
xw.close();
System.out.println("MyBooks的内容已经生成XML文件");
}
}
由于编码的问题,会出现Error:(1, 1) java: 非法字符: '\ufeff’错误,所以将即将执行的有右下角的“UTF-8”改成“GBK”运行时选择convert,在运行成功后,改回“UTF-8”重新执行一次,可以参考链接帮助,最后让我们来看看结果
接下我们便会在C盘中找到文件
注意,在C盘中添加文件时会因为权限问题而导致失败,因此我们只需要通过管理员的方式去大概我们使用的编程软件就可以了
让我们看看运行结果
我们在通过我们的软件并相对的操作使其美观些
JSON与GSON
GSON是谷歌提供用来在Java对象和JSON之间进行的映射的Java类库
特点:
(1)速度快,效率高
(2)解析比较方便
(3)代码量少而简洁
1.将对象转换为JSON字符串
步骤:
(1)引入JAR包
(2)在需要转换JSON字符串的位置编写如下代码即可
String json = new Gson().toJSON(要转换的对象)
2.将JSON字符串转换为对象:
步骤:
(1)引入JAR包
(2)在需要转换Java对象的位置, 编写如下代码:
对象 = new Gson().fromJson(JSON字符串,对象类型.class)
总结
对java中的XML模块有了进一步的学习与了解,学习过程中出现了许多的问题虽大多部分解决了,但是还留下了一些小问题,例如:文件你的编码问题而导致的中文乱码,同时,在这块内容里可能还有很多的漏洞,例如:我在前面跳过导入的jar文件和配置的步骤,请多多包涵
最后,洗碗这篇博客对你们有用,谢谢阅览