天天看點

03_java核心類庫_XML與JSONXMLJSON:重點

XML

0-學習任務

掌握xml基礎文法,能自己實作編寫的XML檔案。
           

1-XML介紹

簡介

可擴充标記語言(eXtensible Markup Language)。
特性:

  1. xml具有平台無關性, 是一門獨立的标記語言.
  2. xml具有自我描述性
           

為什麼學習XML?

1. 網絡資料傳輸.
 2. 資料存儲
 3. 配置檔案
           

XML檔案

.XML檔案是儲存XML資料的一種方式
XML資料也可以以其他的方式存在(如在記憶體中建構XML資料)。
不要将XML語言狹隘的了解成XML檔案。
           

2-XML文法

XML文法格式

1. XML文檔聲明
 <?xml version="1.0" encoding="UTF-8"?>
2. 标記 ( 元素 / 标簽 / 節點) 
   XML文檔,由一個個的标記組成.
   文法:
     開始标記(開放标記): <标記名稱>
     結束标記(閉合标記): </标記名稱>
     标記名稱:  自定義名稱,必須遵循以下命名規則:
1.名稱可以含字母、數字以及其他的字元
2.名稱不能以數字或者标點符号開始
3.名稱不能以字元 “xml”(或者 XML、Xml)開始
4.名稱不能包含空格,不能包含冒号(:)
5.名稱區分大小寫
     标記内容:  開始标記與結束标記之間 ,是标記的内容.
   例如 ,我們通過标記, 描述一個人名:
     <name>李偉傑</name>
3. 一個XML文檔中, 必須有且且僅允許有一個根标記.
   正例:
     <names>
       <name>張三</name>
       <name>李四</name>
     </names>
   反例:
     <name>李四</name>
     <name>麻子</name>
4. 标記可以嵌套, 但是不允許交叉.
   正例:
     <person>
       <name>李四</name>
       <age>18</age>
     </person>
   反例:
     <person>
       <name>李四<age></name>
       18</age>
     </person>
5. 标記的層級稱呼 (子标記, 父标記 , 兄弟标記, 後代标記 ,祖先标記)
   例如:
     <persons>
       <person>
         <name>李四</name>
         <length>180cm</length>
       </person>
       <person>
         <name>李四</name>
         <length>200cm</length>
       </person>
     </persons>
   name是person的子标記.也是person的後代标記
   name是persons的後代标記.
   name是length的兄弟标記.
   person是name的父标記.
   persons是name的祖先标記.
6. 标記名稱 允許重複
7. 标記除了開始和結束 , 還有屬性.
   标記中的屬性, 在标記開始時 描述, 由屬性名和屬性值 組成.
   格式:
     在開始标記中, 描述屬性.
     可以包含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>
8. 注釋
注釋不能寫在文檔文檔聲明前
注釋不能嵌套注釋
   格式:
     注釋開始:  <!--
     注釋結束:  -->
           

案例:

描述一組圖書books, 至少包含3本書
   圖書book包含
     圖書名稱name
     圖書簡介info ,
     以及屬性id 
<?xml version="1.0" encoding="UTF-8"?>
<books>
 
</books>
           

文法進階CDATA(了解)

CDATA
CDATA 是不應該由 XML 解析器解析的文本資料。
像 "<" 和 "&" 字元在 XML 元素中都是非法的。
"<" 會産生錯誤,因為解析器會把該字元解釋為新元素的開始。
"&" 會産生錯誤,因為解析器會把該字元解釋為字元實體的開始。
某些文本,比如 JavaScript 代碼,包含大量 "<" 或 "&" 字元。為了避免錯誤,可以将腳本代
碼定義為 CDATA。
CDATA 部分中的所有内容都會被解析器忽略。
CDATA 部分由 "<![CDATA[" 開始,由 "]]>" 結束
           

3-解析XML的方式

JAVA解析XML掌握

面試題*

問: Java中有幾種XML解析方式 ? 分别是什麼 ? 有什麼樣的優缺點 ?
答: 四種.
 1. SAX解析
     解析方式是事件驅動機制 !
     SAX解析器, 逐行讀取XML檔案解析 , 每當解析到一個标簽的開始/結束/内容/屬性時,觸
發事件.
     我們可以編寫程式在這些事件發生時, 進行相應的處理.
     優點:
     分析能夠立即開始,而不是等待所有的資料被處理
       逐行加載,節省記憶體.有助于解析大于系統記憶體的文檔
有時不必解析整個文檔,它可以在某個條件得到滿足時停止解析.
     缺點:
       1. 單向解析,無法定位文檔層次,無法同時通路同一文檔的不同部分資料(因為逐
行解析, 當解析第n行是, 第n-1行已經被釋放了, 無法在進行操作了).
       2. 無法得知事件發生時元素的層次, 隻能自己維護節點的父/子關系.
       3. 隻讀解析方式, 無法修改XML文檔的内容.
    
 2. DOM解析
 是用與平台和語言無關的方式表示XML文檔的官方W3C标準,分析該結構通常需要加載整個
文檔和記憶體中建立文檔樹模型.程式員可以通過操作文檔樹, 來完成資料的擷取 修改 删除等.
     優點:
       文檔在記憶體中加載, 允許對資料和結構做出更改.
通路是雙向的,可以在任何時候在樹中雙向解析資料。
     缺點:
       文檔全部加載在記憶體中 , 消耗資源大.
 3. JDOM解析
     目的是成為Java特定文檔模型,它簡化與XML的互動并且比使用DOM實作更快。由于是第一
個Java特定模型,JDOM一直得到大力推廣和促進。
     JDOM文檔聲明其目的是“使用20%(或更少)的精力解決80%(或更多)Java/XML問題”
(根據學習曲線假定為20%)
            優點:
            使用具體類而不是接口,簡化了DOM的API。
            大量使用了Java集合類,友善了Java開發人員。
            缺點:
            沒有較好的靈活性。
            性能不是那麼優異。
 4. DOM4J解析
     它是JDOM的一種智能分支。它合并了許多超出基本XML文檔表示的功能,包括內建的XPath
支援、XML Schema支援以及用于大文檔或流化文檔的基于事件的處理。它還提供了建構文檔表示的選項,
DOM4J是一個非常優秀的Java XML API,具有性能優異、功能強大和極端易用使用的特點,同時它也是一
個開放源代碼的軟體。如今你可以看到越來越多的Java軟體都在使用DOM4J來讀寫XML。
     目前許多開源項目中大量采用DOM4J , 例如:Hibernate
           

4-XML解析

DOM4J解析XML掌握

步驟:
 1. 引入jar檔案 dom4j.jar
 2. 建立一個指向XML檔案的輸入流
     FileInputStream fis = new FileInputStream("xml檔案的位址");
 3. 建立一個XML讀取工具對象
     SAXReader sr = new SAXReader();
 4. 使用讀取工具對象, 讀取XML文檔的輸入流 , 并得到文檔對象
     Document doc = sr.read(fis);  
 5. 通過文檔對象, 擷取XML文檔中的根元素對象
     Element root = doc.getRootElement();
           

文檔對象

指的是加載到記憶體的 整個XML文檔.
常用方法:
 1. 通過文檔對象, 擷取XML文檔中的根元素對象
     Element root = doc.getRootElement();
 2. 添加根節點
     Element root = doc.addElement("根節點名稱");
           

元素對象Element

指的是XML文檔中的單個節點.
常用方法:
 1. 擷取節點名稱
     String getName();
 2. 擷取節點内容
     String getText();
 3. 設定節點内容
     String setText();
 4. 根據子節點的名稱 , 擷取比對名稱的第一個子節點對象.
     Element element(String 子節點名稱);
 5. 擷取所有的子節點對象
     List<Element> elements();
 6. 擷取節點的屬性值
     String attributeValue(String 屬性名稱);
 7. 擷取子節點的内容
     String elementText(String 子節點名稱);
 8. 添加子節點
     Element addElement(String 子節點名稱);
 9. 添加屬性
     void addAttribute(String 屬性名,String 屬性值);
           

解析本地檔案案例

//1.  擷取檔案的輸入流
 FileInputStream fis = new
FileInputStream("C:\\code\\35\\code1\\day03_XML\\src\\books.xml");
 //2.  建立XML讀取工具對象
 SAXReader sr = new SAXReader();
 //3.  通過讀取工具, 讀取XML文檔的輸入流 , 并得到文檔對象
 Document doc = sr.read(fis);
 //4.  通過文檔對象 , 擷取文檔的根節點對象
 Element root = doc.getRootElement();
 //5.  通過根節點, 擷取所有子節點
 List<Element> es = root.elements();
 //6.  循環周遊三個book
 for (Element e : es) {
   //1.  擷取id屬性值
   String id = e.attributeValue("id");
   //2.  擷取子節點name , 并擷取它的内容
   String name = e.element("name").getText();
   //3.  擷取子節點info , 并擷取它的内容
   String info = e.element("info").getText();
   System.out.println("id="+id+",name="+name+",info="+info);
 }
           

解析網絡檔案案例

String phone = "18516955565";
   //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 province = result.elementText("province");
     String city = result.elementText("city");
     if(province.equals(city)){
       System.out.println("手機号碼歸屬地為:"+city);
     }else{
       System.out.println("手機号碼歸屬地為:"+province+" "+city);
     }
   }else{
     System.out.println("請輸入正确的手機号碼");
   }
           

5-XPATH解析

DOM4J-XPATH解析XML

路徑表達式

通過路徑快速的查找一個或一組元素
路徑表達式:
 1. /  :  從根節點開始查找
 2. // :  從發起查找的節點位置 查找後代節點 ***
 3. .  :  查找目前節點
 4. .. :  查找父節點
 5. @  :  選擇屬性. * 
       屬性使用方式:
       [@屬性名='值']
       [@屬性名>'值']
       [@屬性名<'值']
       [@屬性名!='值']
       
 books:  路徑: //book[@id='1']//name
 books
 book id=1
 name
 info
 book id=2
 name
 info
           

使用步驟

通過Node類的兩個方法, 來完成查找:
(Node是 Document 與 Element 的父接口)
方法1.  
 //根據路徑表達式, 查找比對的單個節點
 Element e = selectSingleNode("路徑表達式");
方法2.
 List<Element> es = selectNodes("路徑表達式");
案例:
 String phone = "18313935565";
   //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);
   Node node = doc.selectSingleNode("//company");
   System.out.println("營運商:"+node.getText());
   is.close();
           

6-XML生成

Java生成XML熟悉

步驟:
 1. 通過文檔幫助器 (DocumentHelper) , 建立空的文檔對象
     Document doc = DocumentHelper.createDocument();
 2. 通過文檔對象, 向其中添加根節點
     Element root = doc.addElement("根節點名稱");
 3. 通過根節點對象root , 豐富我們的子節點
     Element e = root.addElement("元素名稱");
 4. 建立一個檔案輸出流 ,用于存儲XML檔案
     FileOutputStream fos = new FileOutputStream("要存儲的位置");
 5. 将檔案輸出流, 轉換為XML文檔輸出流
     XMLWriter xw = new XMLWriter(fos); 
 6. 寫出文檔
     xw.write(doc);
 7. 釋放資源
     xw.close();
案例:
   //1.  通過文檔幫助器, 建立空的文檔對象
   Document doc = DocumentHelper.createDocument();
   //2.  向文檔對象中, 加入根節點對象
   Element books = doc.addElement("books");
   //3.  向根節點中 豐富子節點
   for(int i=0;i<1000;i++) {
     //向根節點中加入1000個book節點.
     Element book = books.addElement("book");
     //向book節點, 加入id屬性
     book.addAttribute("id", 1+i+"");
     //向book節點中加入name和info節點
     Element name = book.addElement("name");
     Element info = book.addElement("info");
     name.setText("蘋果"+i);
     info.setText("哈哈哈"+i);
   }
   //4.  建立檔案的輸出流
   FileOutputStream fos = new FileOutputStream("c:\\books.xml");
   //5.  将檔案輸出流 , 轉換為XML文檔輸出流
   XMLWriter xw = new XMLWriter(fos);
   //6.  寫出XML文檔
   xw.write(doc);
   //7.  釋放資源
   xw.close();
   System.out.println("代碼執行完畢");
           

XStream的使用了解

快速的将Java中的對象, 轉換為 XML字元串.
使用步驟:
1. 建立XStream 對象
   XStream x = new XStream();
 [2].修改類生成的節點名稱 (預設節點名稱為 包名.類名)
   x.alias("節點名稱",類名.class);
 3. 傳入對象 , 生成XML字元串
   String xml字元串 = x.toXML(對象);
案例:
 Person p = new Person(1001, "張三", "不詳");
 XStream x = new XStream();
 x.alias("haha", Person.class);
 String xml = x.toXML(p);
 System.out.println(xml);
           

JSON:重點

0-學習任務

掌握JSON解析。
           

1-JSON介紹

簡介:
JSON:  JavaScript Object Notation JS對象簡譜 , 是一種輕量級的資料交換格式.
           

對象格式

一本書
書名
簡介
java
   class Book{
     private String name;
     private String info;
     get/set...
   }
   Book b = new Book();
   b.setName(“金蘋果”);
   b.setInfo(“種蘋果”);
   ...
js:
   var b = new Object();
   b.name = "金蘋果";
   b.info = "種蘋果";
   
 XML:
 <book>
 <name>金蘋果</name>
 <info>種蘋果</info>
 </book>
 JSON:
 {
 "name":"金蘋果",
 "info":"種蘋果"
 }
一個對象, 由一個大括号表示.
   括号中 描述對象的屬性 . 通過鍵值對來描述對象的屬性
   (可以了解為, 大括号中, 包含的是一個個的鍵值對.)
   格式:
鍵與值之間使用冒号連接配接, 多個鍵值對之間使用逗号分隔.
鍵值對的鍵 應使用引号引住 (通常Java解析時, 鍵不使用引号會報錯. 而JS能正确解
析.)
鍵值對的值, 可以是JS中的任意類型的資料
           

數組格式

在JSON格式中可以與對象互相嵌套
[元素1,元素2...]
           

案例:

{
        "name":"偉傑老師",
        "age":18,
        "pengyou":["張三","李四","王二","麻子",{
              "name":"野馬老師",
              "info":"像匹野馬一樣狂奔在技術鑽研的道路上"
           }],
        "heihei":{
          "name":"大長刀",
          "length":"40m"
       }
     }
           

2-JSON解析(重點)

Java與JSON

做什麼?
 将Java中的對象 快速的轉換為 JSON格式的字元串.
 将JSON格式的字元串, 轉換為Java的對象.
           

Gson:推薦使用,較穩定

  • 将對象轉換為JSON字元串
    轉換JSON字元串的步驟:
      1.  引入JAR包
      2.  在需要轉換JSON字元串的位置編寫如下代碼即可:
        String json = new Gson().toJSON(要轉換的對象);
       
    案例:
      Book b = BookDao.find();
      String json = new Gson().toJson(b);
      System.out.println(json);
               
  • 将JSON字元串轉換成對象
1.  引入JAR包
2.  在需要轉換Java對象的位置, 編寫如下代碼:
    對象 = new Gson().fromJson(JSON字元串,對象類型.class);
案例:
  String json = "{\"id\":1,\"name\":\"金蘋果\",\"author\":\"李偉傑
\",\"info\":\"嘿嘿嘿嘿嘿嘿\",\"price\":198.0}";
  Book book = new Gson().fromJson(json, Book.class);
  System.out.println(book);
           

FastJson:有漏洞,但符合國内開發環境,常用

  • 将對象轉換為JSON字元串
    轉換JSON字元串的步驟:
      1.  引入JAR包
      2.  在需要轉換JSON字元串的位置編寫如下代碼即可:
        String json=JSON.toJSONString(要轉換的對象);
       
    案例:
      Book b = BookDao.find();
      String json=JSON.toJSONString(b);
      System.out.println(json);
               
  • 将JSON字元串轉換為對象
    1.  引入JAR包
      2.  在需要轉換Java對象的位置, 編寫如下代碼:
       類型 對象名=JSON.parseObject(JSON字元串, 類型.class);
    或
          List<類型> list=JSON.parseArray(JSON字元串,類型.class);
    案例:
      String json = "{\"id\":1,\"name\":\"金蘋果\",\"author\":\"李偉傑
    \",\"info\":\"嘿嘿嘿嘿嘿嘿\",\"price\":198.0}";
      Book book = JSON.parseObject(json, Book.class);
      System.out.println(book);