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>