您的位置:首页 > 理论基础 > 计算机网络

Android网络应用(三)——网络数据解析

2016-06-22 10:33 501 查看
解析 XML 格式数据
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());
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: