Android网络应用(三)——网络数据解析
2016-06-22 10:33
501 查看
解析 XML 格式数据
Pull 解析方式XmlPullParserFactoryXmlPullParser
SAX 解析方式
创建
实例
解析JSON格式数据
JSON 格式的内容
使用 JSONObject
使用 GSON
解析单个json数据
解析JSON数组TypeToken
实际应用
在网络上传输数据时最常用的格式有两种,XML 和 JSON.
startDocument()方法会在开始 XML 解析的时候调用,startElement()方法会在开始解析某个结点的时候调用,characters()方法会在获取结点中内容的时候调用,endElement()方法会在完成解析某个结点的时候调用,endDocument()方法会在完成整个 XML 解析的时候调用。其中,startElement()、characters()和 endElement()这三个方法是有参数的,从 XML 中解析出的数据就会以参数的形式传入到这些方法中。需要注意的是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容解析出来,我们需要针对这种情况在代码中做好控制。
每当开始解析某个结点的时候, startElement()方法就会得到调用,其中 localName 参数记录着当前结点的名字,这里我们把它记录下来。接着在解析结点中具体内容的时候就会调用 characters()方法,我们会根据当前的结点名进行判断,将解析出的内容添加到哪一个StringBuilder 对象中。最后在 endElement()方法中进行判断,如果 app 结点已经解析完成,就打印出 id、name 和 version 的内容。需要注意的是,目前 id、name 和 version 中都可能是包括回车或换行符的,因此在打印之前我们还需要调用一下 trim()方法,并且打印完成后还要将 StringBuilder 的内容清空掉,不然的话会影响下一次内容的读取。
先是创建了一个 SAXParserFactory 的对象,然后再获取到XMLReader 对象,接着将我们编写的 ContentHandler 的实例设置到 XMLReader 中,最后调用 parse()方法开始执行解析就好了。
在服务器中定义的是一个 JSON 数组,因此这里首先是将服务器返回的数据传入到了一个 JSONArray 对象中。然后循环遍历这个 JSONArray,从中取出的每一个元素都是一个 JSONObject 对象,每个 JSONObject 对象中又会包含 id、name 和version 这些数据。接下来只需要调用 getString()方法将这些数据取出,并打印出来即可。
比如:
Pull 解析方式XmlPullParserFactoryXmlPullParser
SAX 解析方式
创建
实例
解析JSON格式数据
JSON 格式的内容
使用 JSONObject
使用 GSON
解析单个json数据
解析JSON数组TypeToken
实际应用
在网络上传输数据时最常用的格式有两种,XML 和 JSON.
解析 XML 格式数据
<apps> <app> <id>1</id> <name>Google Maps</name> <version>1.0</version> </app> <app> <id>2</id> <name>Chrome</name> <version>2.1</version> </app> <app> <id>3</id> <name>Google Play</name> <version>2.3</version> </app> </apps>
Pull 解析方式——XmlPullParserFactory、XmlPullParser
比如,利用HttpGet 直接获取该网页上面的如上xml文件内容,并获取到响应response。自定义parseXMLWithPull(response)方法。private void parseXMLWithPull(String xmlData) { try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = factory.newPullParser(); xmlPullParser.setInput(new StringReader(xmlData)); int eventType = xmlPullParser.getEventType(); String id = ""; String name = ""; String version = ""; while (eventType != XmlPullParser.END_DOCUMENT) { String nodeName = xmlPullParser.getName(); switch (eventType) { // 开始解析某个结点 case XmlPullParser.START_TAG: { if ("id".equals(nodeName)) { id = xmlPullParser.nextText(); } else if ("name".equals(nodeName)) { name = xmlPullParser.nextText(); } else if ("version".equals(nodeName)) { version = xmlPullParser.nextText(); } break; } // 完成解析某个结点 case XmlPullParser.END_TAG: { if ("app".equals(nodeName)) { Log.d("MainActivity", "id is " + id); Log.d("MainActivity", "name is " + name); Log.d("MainActivity", "version is " + version); } break; } default: break; } eventType = xmlPullParser.next(); } } catch (Exception e) { e.printStackTrace(); } }
SAX 解析方式
AX 解析也是一种特别常用的 XML 解析方式,虽然它的用法比 Pull 解析要复杂一些,但在语义方面会更加的清楚。创建
1、新建一个类继承自 DefaultHandler,并重写父类的五个方法。public class MyHandler extends DefaultHandler { @Override public void startDocument() throws SAXException { } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { } @Override public void characters(char[] ch, int start, int length) throws SAXException { } @Override public void endElement(String uri, String localName, String qName) throws SAXException { } @Override public void endDocument() throws SAXException { } }
startDocument()方法会在开始 XML 解析的时候调用,startElement()方法会在开始解析某个结点的时候调用,characters()方法会在获取结点中内容的时候调用,endElement()方法会在完成解析某个结点的时候调用,endDocument()方法会在完成整个 XML 解析的时候调用。其中,startElement()、characters()和 endElement()这三个方法是有参数的,从 XML 中解析出的数据就会以参数的形式传入到这些方法中。需要注意的是,在获取结点中的内容时,characters()方法可能会被调用多次,一些换行符也被当作内容解析出来,我们需要针对这种情况在代码中做好控制。
实例
//解析类实现 public class ContentHandler extends DefaultHandler { private String nodeName; private StringBuilder id; private StringBuilder name; private StringBuilder version; @Override public void startDocument() throws SAXException { id = new StringBuilder(); name = new StringBuilder(); version = new StringBuilder(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { // 记录当前结点名 nodeName = localName; } @Override public void characters(char[] ch, int start, int length) throws SAXException { // 根据当前的结点名判断将内容添加到哪一个StringBuilder对象中 if ("id".equals(nodeName)) { id.append(ch, start, length); } else if ("name".equals(nodeName)) { name.append(ch, start, length); } else if ("version".equals(nodeName)) { version.append(ch, start, length); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("app".equals(localName)) { Log.d("ContentHandler", "id is " + id.toString().trim()); Log.d("ContentHandler", "name is " + name.toString().trim()); Log.d("ContentHandler", "version is " + version.toString().trim()); // 最后要将StringBuilder清空掉 id.setLength(0); name.setLength(0); version.setLength(0); } } @Override public void endDocument() throws SAXException { } }
每当开始解析某个结点的时候, startElement()方法就会得到调用,其中 localName 参数记录着当前结点的名字,这里我们把它记录下来。接着在解析结点中具体内容的时候就会调用 characters()方法,我们会根据当前的结点名进行判断,将解析出的内容添加到哪一个StringBuilder 对象中。最后在 endElement()方法中进行判断,如果 app 结点已经解析完成,就打印出 id、name 和 version 的内容。需要注意的是,目前 id、name 和 version 中都可能是包括回车或换行符的,因此在打印之前我们还需要调用一下 trim()方法,并且打印完成后还要将 StringBuilder 的内容清空掉,不然的话会影响下一次内容的读取。
private void parseXMLWithSAX(String xmlData) { try { SAXParserFactory factory = SAXParserFactory.newInstance(); XMLReader xmlReader = factory.newSAXParser().getXMLReader(); ContentHandler handler = new ContentHandler(); // 将ContentHandler的实例设置到XMLReader中 xmlReader.setContentHandler(handler); // 开始执行解析 xmlReader.parse(new InputSource(new StringReader(xmlData))); } catch (Exception e) { e.printStackTrace(); } }
先是创建了一个 SAXParserFactory 的对象,然后再获取到XMLReader 对象,接着将我们编写的 ContentHandler 的实例设置到 XMLReader 中,最后调用 parse()方法开始执行解析就好了。
解析JSON格式数据
比起 XML,JSON 的主要优势在于它的体积更小,在网络上传输的时候可以更省流量。但缺点在于,它的语义性较差,看起来不如 XML 直观。JSON 格式的内容:
[{"id":"5","version":"5.5","name":"Angry Birds"}, {"id":"6","version":"7.0","name":"Clash of Clans"}, {"id":"7","version":"3.5","name":"Hey Day"}]
使用 JSONObject
private void parseJSONWithJSONObject(String jsonData) { try { JSONArray jsonArray = new JSONArray(jsonData); for (int i = 0; i < jsonArray.length(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String id = jsonObject.getString("id"); String name = jsonObject.getString("name"); String version = jsonObject.getString("version"); Log.d("MainActivity", "id is " + id); Log.d("MainActivity", "name is " + name); Log.d("MainActivity", "version is " + version); } } catch (Exception e) { e.printStackTrace(); } }
在服务器中定义的是一个 JSON 数组,因此这里首先是将服务器返回的数据传入到了一个 JSONArray 对象中。然后循环遍历这个 JSONArray,从中取出的每一个元素都是一个 JSONObject 对象,每个 JSONObject 对象中又会包含 id、name 和version 这些数据。接下来只需要调用 getString()方法将这些数据取出,并打印出来即可。
使用 GSON
GSON 并没有被添加到 Android 官方的 API 中,因此如果想要使用这个功能的话,则必须要在项目中添加一个 GSON 的 Jar 包。首先我们需要将 GSON 的资源压缩包下载下来,下载地址是:http://code.google.com/p/google-gson/downloads/list。其中 gson-2.2.4.jar 这个文件就是我们所需要的了,现在将它拷贝到 NetworkTest 项目的libs 目录下,GSON 库就会自动添加到 NetworkTest 项目中了,解析单个json数据
GSON最神奇之处:可以将一段 JSON 格式的字符串自动映射成一个对象,从而不需要我们再手动去编写代码进行解析了。比如:
//比如说一段 JSON 格式的数据如下所示: {"name":"Tom","age":20} //以定义一个 Person 类,并加入 name 和 age 这两个字段,然后只需简单地调用如下代码就可以将 //JSON 数据自动解析成一个 Person 对象了 Gson gson = new Gson(); Person person = gson.fromJson(jsonData, Person.class);
解析JSON数组——TypeToken
List<Person> people = gson.fromJson(jsonData, new TypeToken<List<Person>>(){}.getType());
实际应用
//类对象 public class App { private String id; private String name; private String version; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } }
private void parseJSONWithGSON(String jsonData) { Gson gson = new Gson(); List<App> appList = gson.fromJson(jsonData, new TypeToken<List<App>>() {}.getType()); for (App app : appList) { Log.d("MainActivity", "id is " + app.getId()); Log.d("MainActivity", "name is " + app.getName()); Log.d("MainActivity", "version is " + app.getVersion()); } }
相关文章推荐
- Python即时网络爬虫:API说明
- 计算机网络学习笔记二
- HttpClient
- 项目部署之多项目war配置同一个Tomcat利用不同端口访问项目(省略项目名/projectName 直接http://localhost:8090/)
- WEB服务器、应用程序服务器、HTTP服务器区别
- [Protocol Analysis]Wireshark capture packet tcp udp checksum error
- 神经网络
- Android OkHttp完全解析 是时候来了解OkHttp了
- Socket Server-基于NIO的TCP服务器
- uri中为什么本地文件file后面跟三个斜杠, http等协议跟两个斜杠?
- HTTP协议详解
- 常见http状态
- html标记语言的标准写法-参考自http://www.zhihu.com/question/20797118/answer/16212312
- Android Studio 编译不通过,报错“找不到org.apache.http.HttpEntity”
- iOS的HTTP请求和请求回执类用法小结
- Neural Networks and Deep Learning 学习笔记(五)
- 计算机网络学习笔记一
- Linux打印出netstat -anp 里的Send_Q发送堵的TCP连接
- HTTP 301跳转与302跳转的区别
- TCP服务器端和客户端程序设计