分析Json/Xml的解析過程


json和xml都是用來進行數據的傳輸和交換的,是目前用來傳輸數據用的最多的兩種技術,下面我們分別來認識一下它們及其解析過程

 

一、json

1、json簡介

  • JSON是一種基於文本的輕量級數據交換格式,源自JavaScript,用於Web服務和其他連接的應用程序,易於人閱讀和編寫, 同時也易於機器解析和生成
  • JSON是存儲和交換文本信息的語法,類似XML
  • JSON采用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等),這些特性使JSON成為理想的數據交換語言

2、json語法

  JSON只定義了兩個數據結構:對象和數組。對象是一組名稱 - 值對,而數組是值列表。JSON定義了七種值類型:字符串,數字,對象,數組,true,false和null。

  以下示例顯示包含名稱 - 值對的示例對象的JSON數據。名稱的值"phoneNumbers"是一個數組,其元素是兩個對象。

{
   "firstName": "Duke",
   "lastName": "Java",
   "age": 18,
   "streetAddress": "100 Internet Dr",
   "city": "JavaTown",
   "state": "JA",
   "postalCode": "12345",
   "phoneNumbers": [
      { "Mobile": "111-111-1111" },
      { "Home": "222-222-2222" }
   ]
}

  JSON具有以下語法:

 

  • 對象用大括號({}括起來,它們的名稱 - 值對用逗號(,分隔,一對中的名稱和值用冒號(:分隔對象中的名稱是字符串,而值可以是七種值類型中的任何一種,包括另一個對象或數組。

 

  • 數組括在括號([])中,它們的值用逗號(,分隔數組中的每個值可以是不同的類型,包括另一個數組或對象。
  • 當對象和數組包含其他對象或數組時,數據具有樹狀結構

  JSON通常用作通用格式,用於序列化和反序列化通過Internet相互通信的應用程序中的數據。這些應用程序使用不同的編程語言創建,並在不同的環境中運行。JSON適用於這種情況,因為它是一個開放標准,易於讀寫,並且比其他表示更緊湊

3、生成和解析json數據

  為了生成和解析JSON數據,有兩種編程模型,類似於用於XML文檔的編程模型。

  • 對象模型創建一個表示內存中JSON數據的樹。然后可以導航,分析或修改樹。這種方法最靈活,允許進行需要訪問樹的完整內容的處理。但是,它通常比流模型慢,需要更多內存。對象模型通過一次導航整個樹來生成JSON輸出。

  • 流模型使用基於事件的解析器,一次讀取一個元素的JSON數據。當對象或數組開始或結束,找到鍵或找到值時,解析器生成事件並停止處理。應用程序代碼可以處理或丟棄每個元素,然后解析器繼續執行下一個事件。這種方法適用於本地處理,其中元素的處理不需要來自其余數據的信息。流模型通過一次使用一個元素進行函數調用來生成給定流的JSON輸出。

  3.1使用解析器讀取JSON數據

  流API是解析JSON文本的最有效方法。以下代碼演示了如何創建JsonParser對象以及如何使用事件解析JSON數據:

import javax.json.Json;
import javax.json.stream.JsonParser;
...
JsonParser parser = Json.createParser(new StringReader(jsonData));
while (parser.hasNext()) {
   JsonParser.Event event = parser.next();
   switch(event) {
      case START_ARRAY:
      case END_ARRAY:
      case START_OBJECT:
      case END_OBJECT:
      case VALUE_FALSE:
      case VALUE_NULL:
      case VALUE_TRUE:
         System.out.println(event.toString());
         break;
      case KEY_NAME:
         System.out.print(event.toString() + " " +
                          parser.getString() + " - ");
         break;
      case VALUE_STRING:
      case VALUE_NUMBER:
         System.out.println(event.toString() + " " +
                            parser.getString());
         break;
   }
}

  此示例包含三個步驟。

    1. 通過調用Json.createParser靜態方法獲取解析器實例

    2. 使用JsonParser.hasNext和 JsonParser.next方法迭代解析器事件

    3. 對每個元素執行本地處理。

  該示例顯示了解析器中的十種可能的事件類型。解析器的next方法將其推進到下一個事件。對於事件類型KEY_NAMEVALUE_STRINGVALUE_NUMBER,您可以通過調用方法獲取元素的內容 JsonParser.getString對於 VALUE_NUMBER事件,您還可以使用以下方法:JsonParser.isIntegralNumber

  • JsonParser.getInt
  • JsonParser.getLong
  • JsonParser.getBigDecimal

  有關javax.json.stream.JsonParser 更多信息,請參閱該接口的Java EE API參考

  此示例的輸出如下:

START_OBJECT
KEY_NAME firstName - VALUE_STRING Duke
KEY_NAME lastName - VALUE_STRING Java
KEY_NAME age - VALUE_NUMBER 18
KEY_NAME streetAddress - VALUE_STRING 100 Internet Dr
KEY_NAME city - VALUE_STRING JavaTown
KEY_NAME state - VALUE_STRING JA
KEY_NAME postalCode - VALUE_STRING 12345
KEY_NAME phoneNumbers - START_ARRAY
START_OBJECT
KEY_NAME type - VALUE_STRING mobile
KEY_NAME number - VALUE_STRING 111-111-1111
END_OBJECT
START_OBJECT
KEY_NAME type - VALUE_STRING home
KEY_NAME number - VALUE_STRING 222-222-2222
END_OBJECT
END_ARRAY
END_OBJECT

3.2使用生成器編寫JSON數據

  以下代碼演示了如何使用流API將JSON數據寫入文件:

FileWriter writer = new FileWriter("test.txt");
JsonGenerator gen = Json.createGenerator(writer);
gen.writeStartObject()
   .write("firstName", "Duke")
   .write("lastName", "Java")
   .write("age", 18)
   .write("streetAddress", "100 Internet Dr")
   .write("city", "JavaTown")
   .write("state", "JA")
   .write("postalCode", "12345")
   .writeStartArray("phoneNumbers")
      .writeStartObject()
         .write("type", "mobile")
         .write("number", "111-111-1111")
      .writeEnd()
      .writeStartObject()
         .write("type", "home")
         .write("number", "222-222-2222")
      .writeEnd()
   .writeEnd()
.writeEnd();
gen.close();

  此示例通過調用Json.createGenerator靜態方法獲取JSON生成器,該 方法將writer或輸出流作為參數。該示例JSON數據寫入到test.txt 通過嵌套的調用文件writewriteStartArray, writeStartObject,和writeEnd方法。JsonGenerator.close 方法關閉底層的編寫器或輸出流。

 

二、xml

1、xml簡介

  • XML是一種可擴展標記語言,很類似HTML,通過此種標記,計算機之間可以處理包含各種信息的文章等
  • XML的設計宗旨是傳輸數據,而非顯示數據,所以它也是數據傳輸常用的常用工具
  • XML標簽沒有被預定義。您需要自行定義標簽。
  • XML被設計為具有自我描述性
  • XML不是HTML的替代,XML用於傳輸數據,而HTML用於格式化並顯示數據

2、xml語法

  總的來說就是語法比json繁雜多了,這里就不詳細介紹了,有興趣可以自行學習(暴露了我更偏愛json,●ˇ∀ˇ●)

3、xml解析

  xml的三種原生解析方式:

  • DOM:內存消耗大但是便於遍歷.打開文檔,將其轉化為節點樹,然后在其用循環的方式,遍歷節點一一查找
  • SAX:速度快,戰內存少.但是文件結構信息會丟失,采用的是流的處理方式.從起始標簽開始一一往下逐個查找.起始標簽與結尾標簽作為標記來將一組數據存入一個集合中,想水流一樣一直到最尾,然后最后返回集合,集合中就存下了所有的數據(這也應該就是所謂的流處理方式吧).
  • PULL:是Android內置,推薦的一種,相對來說有點類似SAX,也是從上往下,但是它還是已文檔開始與結尾為條件,在其中間進行查找處理,然后分為不同標簽開始逐一查找.

  下面 以網上借鑒的項目為例,展示如何解析xml文件

 3.1 XML文件是一棵樹,首先需要找到對應的節點,然后從節點開始解析,比如搜索找到的就是result/weights/weight 和result/weights/weight 2個節點,分別從這個開始解析:

public ResultInfo onParser(Element rootElement) {
    int resp = -1;
    try {
        String elName = "header/respcode";
        resp = Integer.parseInt(selectNodeString(rootElement, elName));
    } catch (NumberFormatException e) {
        e.printStackTrace();
    }
 
    Log.d(TAG, "resp= " + resp);
 
    if (resp != 0) {
        return null;
    }
 
    ResultInfo searchResultInfo = new ResultInfo();
 
    // Parse Search Weight
    @SuppressWarnings("rawtypes")
    final List <span id="17_nwp" style="float: none; width: auto; height: auto;"><a id="17_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=weight&k0=weight&kdi0=0&luki=5&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">weight</span></a>s = rootElement.selectNodes(rootElement.getPath() + "/"
            + "result/weights/weight");
 
    ResultInfo[] resultFilterInfos = parseVideos(weights);
    if (resultFilterInfos != null) {
        ResultInfo weight = new ResultInfo();
        weight.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultFilterInfos);
        searchResultInfo.putResultInfo(ResultInfo.KEY_WEIGHT, weight);
    }
 
    // Parse Albums
    @SuppressWarnings("rawtypes")
    final List albums = rootElement.selectNodes(rootElement.getPath() + "/"
            + "result/albums/album");
 
    ResultInfo[] resultInfos = parseVideos(albums);
    if (resultInfos != null) {
        ResultInfo album = new ResultInfo();
        album.putResultInfoArray(ResultInfo.KEY_VIDEOS, resultInfos);
        searchResultInfo.putResultInfo(ResultInfo.KEY_SEARCH, album);
    }
 
    return searchResultInfo;
}</span>

 3.2 找到了對應的Node,即從對應的Node開始遞歸的查找,直到找到最小的節點,也就是最基本的單元Element。再對每一個Element進行解析:

private ResultInfo[] parseVideos(final List nodes) {
    if (nodes != null && nodes.size() > 0) {
        final int size = nodes.size();
        final ResultInfo[] vis = new ResultInfo[size];
        int i = 0;
        for (Object o : nodes) {
            if (o instanceof Element) {
                final Element <span id="16_nwp" style="float: none; width: auto; height: auto;"><a id="16_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element = (Element) o;
                ResultInfo vi = parseVideo(videoElement);
                vis[i] = vi;
            }
            i++;
        }
        return vis;
    }
    return null;
}</span>

 3.3 針對獲取到的Element,解析出對應的String將數據傳遞給VideoInfo這個類:

private ResultInfo parseVideo(final Element <span id="13_nwp" style="float: none; width: auto; height: auto;"><a id="13_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element) {
    final String id = videoElement.elementText("album_id");
    final String title = videoElement.elementText("title");
    final String categoryId = videoElement.elementText("category_id");
    final String categoryName = videoElement.elementText("category_name");
    final String count = videoElement.elementText("count");
    final String imgUrl = videoElement.elementText("img180236");
    final String duration = <span id="14_nwp" style="float: none; width: auto; height: auto;"><a id="14_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>Element.elementText("duration");
    final String mainactors = videoElement.elementText("mainactors");
    final String sitename = videoElement.elementText("site_name");
    final String videourl = videoElement.elementText("vedio_url");
    final String sort = videoElement.elementText("sort");
    final String tv_id = videoElement.elementText("tv_id");
    ResultInfo vi = new ResultInfo();
    vi.putString(VideoInfo.ID, id);
    vi.putString(VideoInfo.TITLE, title);
    vi.putString(VideoInfo.CATEGORY_ID, categoryId);
    vi.putString(VideoInfo.CATEGORY_NAME, categoryName);
    vi.putString(VideoInfo.COUNT, count);
    vi.putString(VideoInfo.IMG_URL, imgUrl);
    vi.putString(VideoInfo.DURATION, duration);
    vi.putString(VideoInfo.MAINACTORS, mainactors);
    vi.putString(VideoInfo.SITENAME, sitename);
    vi.putString(VideoInfo.VIDEOURL, <span id="15_nwp" style="float: none; width: auto; height: auto;"><a id="15_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>url);
    vi.putString(VideoInfo.SORT, sort);
    vi.putString(VideoInfo.TV_ID, tv_id);
    return vi;
}</span></span></span>

 3.4 當使用XML解析器將XML數據解析出來之后。需要將這些數據提取出來,也是通過連續2層提取,將數據定位到每個video, 將每個video里的數據傳遞給SearchVideoInfo這個ArrayList,然后將ArrayList中的數據和對應的Adapter數據關聯起來:

public static ArrayList<SearchVideoInfo> getSearchVideoInfo(ResultInfo searchResultInfo) {
 
    ResultInfo resultInfo = null;
    ResultInfo[] <span id="9_nwp" style="float: none; width: auto; height: auto;"><a id="9_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>s = null;
    ArrayList<SearchVideoInfo> searchVideoInfos = null;
 
    if (searchResultInfo != null) {
        resultInfo = searchResultInfo.getResultInfo(ResultInfo.KEY_SEARCH);
    }
 
    if (resultInfo != null) {
        videos = resultInfo.getResultInfoArray(ResultInfo.KEY_VIDEOS);
    }
 
    if (videos != null && videos.length > 0) {
 
        searchVideoInfos = new ArrayList<SearchVideoInfo>(<span id="10_nwp" style="float: none; width: auto; height: auto;"><a id="10_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>s.length);
 
        for (ResultInfo video : videos) {
            SearchVideoInfo searchInfo = new SearchVideoInfo();
 
            searchInfo.setAlbum_id(video.getString(VideoInfo.ID));
            searchInfo.setTitle(video.getString(VideoInfo.TITLE));
            searchInfo.setChannel_id(video.getString(VideoInfo.CATEGORY_ID));
            searchInfo.setImgUrl(video.getString(VideoInfo.IMG_URL));
            searchInfo.setDuration(<span id="11_nwp" style="float: none; width: auto; height: auto;"><a id="11_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>.getString(VideoInfo.DURATION));
            searchInfo.setMainActors(video.getString(VideoInfo.MAINACTORS));
            searchInfo.setSiteName(video.getString(VideoInfo.SITENAME));
            searchInfo.setVideo_url(video.getString(VideoInfo.VIDEOURL));
            searchInfo.setOrder(video.getString(VideoInfo.SORT));
            searchInfo.setTv_id(video.getString(VideoInfo.TV_ID));
            // searchInfo.setContinueType(<span id="12_nwp" style="float: none; width: auto; height: auto;"><a id="12_nwl" style="color: #0d4ac6; text-decoration: none;" href="http://cpro.baidu.com/cpro/ui/uijs.php?adclass=0&app_id=0&c=news&cf=1001&ch=0&di=128&fv=18&is_app=0&jk=d131e552bee07477&k=video&k0=video&kdi0=0&luki=6&n=10&p=baidu&q=06011078_cpr&rb=0&rs=1&seller_id=1&sid=7774e0be52e531d1&ssp2=1&stid=0&t=tpclicked3_hc&tu=u1922429&u=http%3A%2F%2Fwww%2Eadmin10000%2Ecom%2Fdocument%2F5388%2Ehtml&urlid=0" target="_blank"><span style="font-size: 14px; float: none; width: auto; color: #0000ff; height: auto;">video</span></a>.getString(VideoInfo.CONTINUETYPE));
 
            searchVideoInfos.add(searchInfo);
        }
    }
 
    if (searchVideoInfos == null) {
        MyLog.e(TAG, "error, getSearchVideoInfo, can not get info");
    }
 
    return searchVideoInfos;
}</span></span></span></span>

 

 參考鏈接:https://www.cnblogs.com/ranzige/p/4600006.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM