b1cat`s

Java XML和JSON

Word count: 1.3kReading time: 6 min
2020/02/22

Java XML和JSON

XML简介

XML(eXtensible Markup Language),一种数据表示格式,可以描述非常复杂的数据结构,常用传输和存储数据。

XML有固定的结构

  • 首行必定是<?xml version="1.0"?> ,可以加上可选的编码

  • 接着是可选的DTD(文档类型定义),<!DOCTYPE not SYSTEM "book.dtd">

  • XML文档内容

    • 只有一个根元素
    • 可以有任意个子元素,元素可以包含属性
    • 元素必须完整嵌套
    • 空元素用<tag/>表示
    • 如果内容有特殊符号,则需html实体编码

    image-20200222234354659

合法的XML不但XML格式正确,数据结构可以被DTD或者XSD验证。

XML还支持:

  • DTD和XSD:验证XML结构和数据是否有效
  • Namespace:XMl节点和属性的名字空间
  • XSLT:把XML转化为另一种文本
  • XPath:一种XML节点查询语言

因为XML是属性结构的文档,它有两种标准的解析API:

  • DOM,一次性读取XML,并在内存中表示为树形结构
  • SAX:以流的形式读取XML,使用事件回调

使用DOM

DOM是Document Object Model的缩写,DOM模型就是把XML结构作为一个树形结构处理,从根节点开始,每个节点都可以包含任意个子节点。

Java提供了DOM API来解析XML

  • Document 代表整个XML文档
  • Element 代表一个XML元素
  • Attribute 代表一个元素的某个属性

使用栗子

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<book id="1">
<name>Java test</name>
<author>b1cat</author>
<isbn lang="CN">123456</isbn>
<tags>
<tag>Java</tag>
<tag>test</tag>
</tags>
</book>
1
2
3
4
5
File input = new File("src/org/b1cat/preJava/book.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(input);
//获得的doc对象本身就是个Node,可以被循环获取子node

DocumentBuilder.parse()用于解析一个XML,它接受InputStream, File或者URL

DOM解析速度慢,内存占用大

使用SAX

SAX(Simple API for XML),是一种基于流的解析方式,边读取XML边解析,并以时间回调的方式让调用者获取数据。因为边读边解析,所以无论XML有多大内存占用很小。

事件:

  • startDocument 开始读取XML文档
  • startElement 读取到一个元素,如<book>
  • characters 读到字符
  • endElement 读取一个结束的元素 如</book>
  • endDocument 读到XML文档结束
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
File input = new File("src/org/b1cat/preJava/book.xml");
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser = spf.newSAXParser();
saxParser.parse(input, new MyHandler);//需要传递回调对象

class MyHandler extends DefaultHandler{ //需要继承DefaultHandler
public void startDocument() throws SAXException {}
public void endDocument() throws SAXException {}
public void startElement(String uri, String localName, String qName, Attribute attribute) throws SAXException {
print('start elemt: ', localName, qName);
}

public void endElement(String uri, String localName, String qName) throws SAXException {
print("end element:", localName, qName);
}

public void characters(char[] ch, int start, int length) throws SAXException {
print("characters:", new String(ch, start, length));
}

public void error(SAXParseException e) throws SAXException {
print("error:", e);
}

void print(Object... objs) {
for (Object obj : objs) {
System.out.print(obj);
System.out.print(" ");
}
System.out.println();
}
}

如果要读取``节点的文本,我们就必须在解析过程中根据startElement()endElement()定位当前正在读取的节点,可以使用栈结构保存,每遇到一个startElement()入栈,每遇到一个endElement()出栈,这样,读到characters()时我们才知道当前读取的文本是哪个节点的。可见,使用SAX API仍然比较麻烦

使用Jackson

观察

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<book id="1">
<name>Java test</name>
<author>b1cat</author>
<isbn lang="CN">123456</isbn>
<tags>
<tag>Java</tag>
<tag>test</tag>
</tags>
</book>

这样的项值对可以对应到JavaBean

1
2
3
4
5
6
7
8
public class Book {
public long id;
public String name;
public String author;
public String isbn;
public List<String> tags;
public String pubDate;
}

幸运的是,一个名叫Jackson的开源的第三方库可以轻松做到XML到JavaBean的转换。我们要使用Jackson,先添加两个Maven的依赖:

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>woodstox-core-asl</artifactId>
<version>4.4.1</version>
</dependency>

使用

1
2
3
4
5
6
7
8
9
10
File input = new File("src/org/b1cat/preJava/book.xml");
JacksonXmlModule module = new JacksonXmlModule();
XmlMapper mapper = new XmlMapper(module);
Book book = mapper.readValue(input, Book.class);
System.out.println(book.id);
System.out.println(book.name);
System.out.println(book.author);
System.out.println(book.isbn);
System.out.println(book.tags);
System.out.println(book.pubDate);

使用JSON

由于XML标签繁琐,解析复杂,在Web上渐渐使用JSON取代。

JSON(JavaScript Object Notation), 它去除了所有JavaScript执行代码,只保留JavaScript对象。

优点:

  • Json只允许UTF-8编码,不存在编码问题
  • Json只匀速使用双引号作为key,转义使用\
  • 浏览器内置JSON支持,javascirpt可以直接处理

格式简单:

  • 键值对{"key":value}
  • 数组[12,34,54]
  • 字符串"abc"
  • 数值12.34
  • 布尔值true, flase
  • 空值 null

读写

1
2
3
jsObj = JSON.parse(jsonstr);

jsonStr = JSON.stringify(jsObj);

Java API

  • JSR 353 API

第三方(XML和Java Bean转化)

  • Jackson
  • Gson
  • Fastjson
  • ..
1
2
3
4
5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.0</version>
</dependency>
CATALOG
  1. 1. Java XML和JSON
    1. 1.0.1. XML简介
    2. 1.0.2. 使用DOM
    3. 1.0.3. 使用SAX
    4. 1.0.4. 使用Jackson
    5. 1.0.5. 使用JSON