您的位置:首页 > 移动开发 > Android开发

Android解析XML数据和Json数据

2015-10-20 12:16 302 查看
本文主要参考以下三篇文章,排名不分先后(瞬间觉得高大上):

/article/4783901.html

/article/7961985.html

/article/1580244.html

很久没更blog了,今天写一写Android常见的两种数据解析—XML和Json。

XML数据解析

Android中经常用到两种方法来解析XML,SAX和PULL。另外还有一种DOM方式,表示没用过,这里就不介绍了,有兴趣的同学可以看看我列出的参考文章的第一篇或者自己度娘。

下面贴一下数据源,来自 w3school

<food>
<name>Belgian Waffles</name>
<price>$5.95</price>
<description>
two of our famous Belgian Waffles with plenty of real maple syrup
</description>
<calories>650</calories>
</food>


先说PULL方式,个人觉得这种方式比较简单,符合自己写代码时的逻辑。

public class PullParser implements FoodParser {
List<Food> mList = null;
Food mFood = null;
@Override
public List<Food> parser(InputStream in) throws Exception {
XmlPullParser mParser = Xml.newPullParser();
mParser.setInput(in,"UTF-8");
//取得当前标签的类型
int eventType = mParser.getEventType();
//根据标签类型判断执行的语句
while (eventType != XmlPullParser.END_DOCUMENT){
switch(eventType){
//XML文件开始
case XmlPullParser.START_DOCUMENT:
mList = new ArrayList<Food>();
break;
//标签开始
case XmlPullParser.START_TAG:
if (mParser.getName().equals("food")){
mFood = new Food();
}else if (mParser.getName().equals("name")){
eventType = mParser.next();
mFood.setName(mParser.getText());
}else if (mParser.getName().equals("price")){
eventType = mParser.next();
mFood.setPrice(mParser.getText());
}else if (mParser.getName().equals("description")){
eventType = mParser.next();
mFood.setDescription(mParser.getText());
}else if (mParser.getName().equals("calories")){
eventType = mParser.next();
mFood.setCalories(Integer.parseInt(mParser.getText()));
}
break;
//标签结束
case XmlPullParser.END_TAG:
if (mParser.getName().equals("food")){
mList.add(mFood);
mFood = null;
}
break;
}
eventType = mParser.next();
}
return mList;
}
}


怎么样逻辑是不是很清晰,XML没有到结尾就一直读取,在开始的时候初始化List,然后根据标签名来获取内容。

再来说SAX方式。这种方式个人感觉麻烦了点,因为要额外定义一个handler来处理XML文件。

public class SaxParser implements FoodParser{
@Override
public List<Food> parser(InputStream in) throws Exception{
SAXParserFactory mFactory = SAXParserFactory.newInstance();
SAXParser mParser = mFactory.newSAXParser();
MyHandler mHandler = new MyHandler();
mParser.parse(in,mHandler);
return mHandler.getFoods();
}

private static class MyHandler extends DefaultHandler {

private List<Food> foods;
private Food food;
private StringBuilder builder;

//返回解析后得到的Food对象集合
public List<Food> getFoods() {
return foods;
}
//文档开始
@Override
public void startDocument() throws SAXException {
super.startDocument();
foods = new ArrayList<Food>();
builder = new StringBuilder();

}
//元素标签开始
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
super.startElement(uri, localName, qName, attributes);
if (localName.equals("food")) {
food = new Food();
}
builder.setLength(0);   //将字符长度设置为0 以便重新开始读取元素内的字符节点
}
//解析内容
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
super.characters(ch, start, length);
builder.append(ch, start, length);  //将读取的字符数组追加到builder中
}
//标签结束
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
if (localName.equals("description")) {
food.setDescription(builder.toString());
} else if (localName.equals("name")) {
food.setName(builder.toString());
} else if (localName.equals("price")) {
food.setPrice(builder.toString());
} else if(localName.equals("calories")){
food.setCalories(Integer.parseInt(builder.toString()));
}
else if (localName.equals("food")) {
foods.add(food);
}
}
}
}


虽然SAX的逻辑也是十分清晰简单,和PULL类似,不过要额外定义一个类,个人表示不爽。

利用Gson解析Json数据

解析Json数据在Android经常使用Gson库来实现,因为它简单方便、简单方便、简单方便,重要的事情说三遍。

Json数据只有三种形式,值,对象,数组。不过通常我们遇到的数据都是嵌套型的,就是对象里面的某个属性可能又是一个对象或者数组。

怎样使用Gson解析嵌套型数据?如果是属性是一个对象,你就需要额外定义一个类来表示这个对象。如果属性是一个数组,你就需要使用一个List表示。

下面看看Json数据,来自慕课网

{"status":1,
"data":[{"id":1,"name":"Tony\u8001\u5e08\u804ashell\u2014\u2014\u73af\u5883\u53d8\u91cf\u914d\u7f6e\u6587\u4ef6","picSmall":"http:\/\/img.mukewang.com\/55237dcc0001128c06000338-300-170.jpg","picBig":"http:\/\/img.mukewang.com\/55237dcc0001128c06000338.jpg","description":"\u4e3a\u4f60\u5e26\u6765shell\u4e2d\u7684\u73af\u5883\u53d8\u91cf\u914d\u7f6e\u6587\u4ef6","learner":12312},
{"id":2,"name":"\u6570\u5b66\u77e5\u8bc6\u5728CSS\u52a8\u753b\u4e2d\u7684\u5e94\u7528","picSmall":"http:\/\/img.mukewang.com\/55249cf30001ae8a06000338-300-170.jpg","picBig":"http:\/\/img.mukewang.com\/55249cf30001ae8a06000338.jpg","description":"\u6570\u5b66\u77e5\u8bc6\u4e0eCSS\u7ed3\u5408\u5b9e\u73b0\u9177\u70ab\u6548\u679c","learner":45625}]}


像上面这个Json数据首先是一个对象,对象里面有两个属性,status和data。status是一个值,data是一个数组,这个数组的元素是对象。所以我们要这样定义表示Json的类。

public class JsonDatas {
int status;
List<Course> data;

public List<Course> getData() {
return data;
}

public void setData(List<Course> data) {
this.data = data;
}

public int getStatus() {
return status;
}

public void setStatus(int status) {
this.status = status;
}

@Override
public String toString() {
return "JsonDatas{" +
"data=" + data +
", status=" + status +
'}';
}
}


注意到了吗,类的名称可以随便命名,但是属性的名称一定要与Json的属性名称一致。上面我使用了List表示Json中的数组,因为数组里面的元素是一个对象,我又另外声明一个类来表示这个对象。

public class Course {
private int id;
private String name;
private String picSmall;
private String picBig;
private String description;
private int leaner;

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public int getLeaner() {
return leaner;
}

public void setLeaner(int leaner) {
this.leaner = leaner;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPicBig() {
return picBig;
}

public void setPicBig(String picBig) {
this.picBig = picBig;
}

public String getPicSmall() {
return picSmall;
}

public void setPicSmall(String picSmall) {
this.picSmall = picSmall;
}

@Override
public String toString() {
return "Course{" +
"description='" + description + '\'' +
", id=" + id +
", name='" + name + '\'' +
", picSmall='" + picSmall + '\'' +
", picBig='" + picBig + '\'' +
", leaner=" + leaner +
'}';
}
}


属性名一定要一致。接下来就是解析了,如果你使用的是原生的API来解释这段数据,你要额外写很多代码,而使用Gson只要这样:

//得到整个对象
JsonDatas data = new Gson().fromJson(body, JsonDatas.class);
//得到data属性的数据
final List<Course> courses = data.getData();


只要两行代码,就将所有的数据封装到了你定义的类之中。使用Gson你关心的只是怎么去定义你的类,不用考虑解析和填充的问题。

因为数据源都在网上,使用了OkHttp获取数据源,关于OkHttp的用法请参考第三篇参考文章

最后给出源码地址:http://download.csdn.net/detail/u013983998/9196075

使用方法:打开Android Studio,新建一个Poroject,再File -> New ->Import Module
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: