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; } }
此示例包含三個步驟。
-
-
通過調用
Json.createParser
靜態方法獲取解析器實例。 -
使用
JsonParser.hasNext
和JsonParser.next
方法迭代解析器事件。 -
對每個元素執行本地處理。
-
該示例顯示了解析器中的十種可能的事件類型。解析器的next
方法將其推進到下一個事件。對於事件類型KEY_NAME
,VALUE_STRING
和VALUE_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
通過嵌套的調用文件write
,writeStartArray
, 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>