Java对XML、JSON的操作
文章目录
XML
XML简介
- XML:可扩展标记语言
- 纯文本表示,跨系统/平台/语言
严格区分大小写
XML组成元素
1、文档声明
2、元素=标签
3、属性
4、注释
5、CDATA区、特殊字符<!CDATA[不想解析的内容]>
文档声明 文档中必须要有一个根标签
<?xml version="1.0" encoding="UTF-8"?>
元素=标签
注:xml必须要有根节点,且只能有一个节点
<student></student>
属性
<student name='xiaoming'></student>
注释
<!--注释-->
CDATA区、特殊字符
< <
> >
" "
' '
XML Schema(XSD,XML Schema Definition)
- 定义xml文档的结构,DTD(Document Type Definition)的继任者
- 支持数据类型,可扩展,功能更完善、强大
XSL
- 扩展样式表语言(eXtensible Stylesheet Language)
- XSL作用于XML,等同于CSS作用于HTML
XML解析
XML解析方法
- 树结构
- DOM:Document Object Model文档对象模型,擅长(小规模)读/写
- 流结构
- SAX:Simple API for XML 流机制解释器(推模式),擅长读
- Stax:The Streaming API for XML 流机制解释器(拉模式),擅长读
DOM
- DocumentBuilder解析类,parse方法
- Node节点主接口,getChildNodes返回一个NodeList
- NodeList节点列表,每个元素是一个Node
- 注意:标签和标签之间的空格也会被上级父节点视为子元素
- Document文档根节点
- Element标签节点元素(每一个标签都是标签节点)
- Text节点(包含在XML元素内的,都算Text节点)
- Attr节点(每个属性节点)
eg:
DOMReader:
//自上而下进行访问
public static void RecursiveTraverse() {
try {
//采用DOM解析XML文件
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
Document document= db.parse("users.xml");
//获取所有的一级子节点
NodeList usersList=document.getChildNodes();
System.out.println("usersList.getLength() = " + usersList.getLength()); //1
for (int i = 0; i < usersList.getLength(); i++) {
Node users=usersList.item(i); //1 users
NodeList userList=users.getChildNodes();//获取二级子节点user的列表
System.out.println("userList.getLength() = " + userList.getLength());//9
for (int j = 0; j < userList.getLength(); j++) {
Node user=userList.item(j);
if (user.getNodeType()==Node.ELEMENT_NODE){
NodeList metaList=user.getChildNodes();
System.out.println("metaList.getLength() = " + metaList.getLength());//7
for (int k = 0; k < metaList.getLength(); k++) {
//到最后一级文本
Node meta=metaList.item(k);
if (meta.getNodeType()==Node.ELEMENT_NODE){
System.out.println("metaList.item(k).getTextContent() = " + metaList.item(k).getTextContent());
}
}
}
}
}
System.out.println();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
//根据名字进行搜索
public static void TraverseBySearch() {
try {
//采用DOM解析XML文件
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse("users.xml");
Element rootElement = document.getDocumentElement();
NodeList nodeList = rootElement.getElementsByTagName("name");
if (nodeList != null) {
for (int i = 0; i < nodeList.getLength(); i++) {
Element element = (Element) nodeList.item(i);
System.out.println("element.getTextContent() = " + element.getTextContent());
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
DOMWriter
public static void main(String[] args) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
//新创建一个Document节点
Document document = builder.newDocument();
if (document != null) {
Element docx = document.createElement("document");
Element element = document.createElement("element");
element.setAttribute("type", "para");
element.setAttribute("alignment", "left");//element增加2个属性
Element object = document.createElement("object");
object.setAttribute("type", "text");
Element text = document.createElement("text");
text.appendChild(document.createTextNode("abcdefg"));//给text节点赋值
Element bold = document.createElement("bold");
bold.appendChild(document.createTextNode("true"));//给bold节点赋值
object.appendChild(text); //把text节点挂在object下
object.appendChild(bold); //把bold节点挂在object下
element.appendChild(object);
docx.appendChild(element);
document.appendChild(docx); //把docx挂在document下
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
//定义目标文件
File file = new File("dom_result.xml");
StreamResult result = new StreamResult(file);
//将xml文件写入到文件中
transformer.transform(source,result);
System.out.println("Write xml file successfully");
}
} catch (ParserConfigurationException | TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
}
SAX(Simple API for XML)
- 采用事件/流模型来解析XML文档,更快速、更轻量
- 有选择的解析和访问,不像DOM加载整个文档,内存要求更低
- SAX对XML文档的解析为一次性读取,不创建/不存储文档对象,很难同时访问文档中的多处数据
- 推模型。当它每发现一个节点就引发一个事件,而我们需要编写这些事件的处理程序。关键类:DefaultHandler
- SAX的5个回调方法
- startDocument 文档开始解析
- endDocument 文档结束解析
- startElement 开始访问元素
- endElement 结束访问元素
- characters 访问元素正文
public class SAXReader {
public static void main(String[] args) throws SAXException, IOException {
XMLReader parser = XMLReaderFactory.createXMLReader();
BoolHandler boolHandler = new BoolHandler();
parser.setContentHandler(boolHandler);
parser.parse("books.xml");
System.out.println("boolHandler = " + boolHandler.getNameList());
}
}
class BoolHandler extends DefaultHandler {
private List<String> nameList;
private boolean title = false;
public List<String> getNameList() {
return nameList;
}
//实现DefaultHandler的5个回调方法
//xml文档加载时
public void startDocument() throws SAXException {
System.out.println("Start parsing document...");
nameList = new ArrayList<String>();
}
//文档解析结束
public void endDocument() throws SAXException {
System.out.println("End");
}
//访问某一个元素
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (qName.equals("title"))
title = true;
}
//结束访问元素
public void endElement(String namespaceURI, String localName, String qName) throws SAXException {
//End of processing current element
if (title) {
title = false;
}
}
//访问元素正文
public void characters(char[] ch, int start, int length) {
if (title) {
String bookTitle = new String(ch, start, length);
System.out.println("bookTitle = " + bookTitle);
nameList.add(bookTitle);
}
}
}
Stax(Streaming API for XML)
- 流模型中的拉模型
- 在遍历文档时,会把感兴趣的部分从读取器中拉出,不需要引发事件,允许我们选择性地处理节点。这大大提高了灵活性,以及整体效率。
- 两套处理API
- 基于指针的API,XMLStreamReader
- 基于迭代器的API,XMLEventReader
eg:
//流模式
public static void readByStream() {
String xmlFile = "books.xml";
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLStreamReader streamReader = null;
try {
streamReader = factory.createXMLStreamReader(new FileReader(xmlFile));
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
//基于指针遍历
try {
while (streamReader.hasNext()) {
int event = streamReader.next();
//如果是元素的开始
if (event == XMLStreamConstants.START_ELEMENT) {
//列出所有书籍名称
if ("title".equalsIgnoreCase(streamReader.getLocalName())) {
System.out.println("title: " + streamReader.getElementText());
}
}
}
streamReader.close();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
//事件模式
public static void readByEvent() {
String xmlFile = "books.xml";
XMLInputFactory factory = XMLInputFactory.newFactory();
boolean titleFlag = false;
try {
//创建基于迭代器的事件读取器对象
XMLEventReader eventReader = factory.createXMLEventReader(new FileReader(xmlFile));
//遍历Event迭代器
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
//如果事件对象是元素的开始
if (event.isStartElement()) {
//转换成开始元素事件对象
StartElement start = event.asStartElement();
//打印元素标签的本地名称
String name = start.getName().getLocalPart();
if (name.equals("title")) {
titleFlag = true;
System.out.println("title:");
}
//取得所有属性
Iterator attrs = start.getAttributes();
while (attrs.hasNext()) {
//打印所有属性信息
Attribute attr = (Attribute) attrs.next();
//System.out.println("attr.getValue() = " + attr.getValue());
}
//如果是正文
if (event.isCharacters()) {
String s = event.asCharacters().getData();
if (null != s && s.trim().length() > 0 && titleFlag) {
System.out.println("s.trim() = " + s.trim());
}
}
//如果事件对象是元素的结束
if (event.isEndElement()) {
EndElement end = event.asEndElement();
String titleName = end.getName().getLocalPart();
if (titleName.equals("title")) {
titleFlag = false;
}
}
}
eventReader.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
}
JSON
JSON简介
-
JavaScript Object Notation,js对象表示法
-
一种轻量级的数据交换格式
-
JSONObject,名称-值对。如"firstName":“John”
- json对象:{“name”:“John”,“email”:“a@b.com”}
- 数据在键值对中
- 数据由逗号分隔
- 花括号保存对象
-
JSONArray,json数组
- 方括号保存数组
- [{K:V,K:V,K:V,…},{}]
- 方括号保存数组
java的JSON处理
jdk本身没有JSON的处理包,故而只能通过在Maven repository中添加工具包来处理
- org.json:JSON官方推荐的解析类
- 简单易用,通用性强,但无法完成复杂功能
- GSON:Google出品。基于反射,可以实现JSON对象、JSON字符串和Java对象互转
- Jackson:号称最快的JSON处理器
JSON主要用途
- JSON生成
- JSON解析
- JSON校验
- 和Java Bean对象进行互解析
- 具有一个无参的构造函数
- 可以包括多个属性,所有属性都是private
- 每个属性都有相应的Getter/Settrt方法
- Java Bean用于封装数据,又可称为POJO(Plain Old Java Object)
eg:
Person.java Java Bean类
public class Person {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<Integer> getScores() {
return scores;
}
public void setScores(List<Integer> scores) {
this.scores = scores;
}
private String name;
private int age;
private List<Integer> scores;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
books.json
{
"books": [
{
"category": "COOKING",
"title": "Everyday Italian",
"author": "Giada De Laurentiis",
"year": "2005",
"price": 30.00
},
{
"category": "CHILDREN",
"title": "Harry Potter",
"author": "J K. Rowling",
"year": "2005",
"price": 29.99
},
{
"category": "WEB",
"title": "Learning XML",
"author": "Erik T. Ray",
"year": "2003",
"price": 39.95
}
]
}
org.json:
pom.xml中添加依赖
<!--org.json Java官方推荐的JSON处理包-->
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180813</version>
</dependency>
//写JSON文件
public static void testJsonObject() {
//构造对象
Person p = new Person();
p.setName("Tom");
p.setAge(20);
p.setScores(Arrays.asList(60,70,80));
//构造JSONObject对象
JSONObject obj = new JSONObject();
//string
obj.put("name", p.getName());
//int
obj.put("age", p.getAge());
//array
obj.put("scores", p.getScores());
//null
//object.put("null", null);
System.out.println(obj);
System.out.println("name: " + obj.getString("name"));
System.out.println("age: " + obj.getInt("age"));
System.out.println("scores: " + obj.getJSONArray("scores"));
}
//读JSON文件
public static void testJsonFile() {
File file = new File("books.json");
try (FileReader reader = new FileReader(file)) {
//读取文件内容到JsonObject对象中
int fileLen = (int) file.length();
char[] chars = new char[fileLen];
reader.read(chars);
String s = String.valueOf(chars);
JSONObject jsonObject = new JSONObject(s);
//开始解析JSONObject对象
JSONArray books = jsonObject.getJSONArray("books");
List<ArrayList> bookList = new ArrayList<>();
for (Object book : books) {
//获取单个JSONObject对象
JSONObject bookObject = (JSONObject) book;
ArrayList book1=new ArrayList();
book1.add(bookObject.getString("author"));
book1.add(bookObject.getString("year"));
book1.add(bookObject.getString("title"));
book1.add(bookObject.getInt("price"));
book1.add(bookObject.getString("category"));
bookList.add(book1);
}
for (ArrayList book : bookList) {
System.out.println(book.get(0)+","+book.get(2));
}
} catch (Exception e) {
e.printStackTrace();
}
}
GSON:(从代码上看,GSON功能更强大,使用更方便,推荐使用GSON解析JSON)
pom.xml中添加依赖
<!--GSON处理JSON包,基于反射,可以实现JSON对象、JSON字符串和Java对象互转-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.7</version>
</dependency>
public static void testJsonObject() {
//构造对象
Person p = new Person();
p.setName("Tom");
p.setAge(20);
p.setScores(Arrays.asList(60,70,80));
//从Java对象到JSON字符串
Gson gson = new Gson();
String s = gson.toJson(p);
System.out.println(s); //{"name":"Tom","age":20,"scores":[60,70,80]}
//从JSON字符串到Java对象
Person p2 = gson.fromJson(s, Person.class);
System.out.println(p2.getName()); //Tom
System.out.println(p2.getAge()); //20
System.out.println(p2.getScores());//[60, 70, 80]
//调用GSON的JsonObject
JsonObject json = gson.toJsonTree(p).getAsJsonObject(); //将整个json解析为一颗树
System.out.println(json.get("name")); //"Tom"
System.out.println(json.get("age")); //20
System.out.println(json.get("scores"));//[60,70,80]
}
public static void testJsonFile() {
Gson gson = new Gson();
File file = new File("books2.json");
try (FileReader reader = new FileReader(file)) {
//从JSON字符串到Java对象
List<Book> books = gson.fromJson(reader, new TypeToken<List<Book>>(){}.getType());
} catch (Exception e) {
e.printStackTrace();
}
}
XML与JSON的比较
- 都是数据交换格式,可读性强,可扩展性高
- 大部分的情况下,JSON更具优势(编码简单,转换方便),而且JSON字符长度一般小于XML,传输效率更高
- XML更加注重标签和顺序,JSON会丢失信息