Java XML和JSON
XML简介
XML(eXtensible Markup Language),一种数据表示格式,可以描述非常复杂的数据结构,常用传输和存储数据。
XML有固定的结构
合法的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);
|
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{ 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
第三方(XML和Java Bean转化)
1 2 3 4 5
| <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.10.0</version> </dependency>
|