​    一起学Android之Xml与Json解析    ​

 

 

在网络中,数据交互通常是以XML和Json的格式进行,所以对这两种格式的数据进行解析,是Android开发中的必备功能,本文以一个简单的小例子,简述Android开发中Xml和Json解析的常用方式,仅供学习分享使用。

概述

在网络中,数据交互通常是以XML和Json的格式进行,所以对这两种格式的数据进行解析,是Android开发中的必备功能,本文以一个简单的小例子,简述Android开发中Xml和Json解析的常用方式,仅供学习分享使用。

XML解析

Android 提供了三种解析XML的方式:SAX(Simple API XML), DOM(Document Object Model), PULL,本文主要讲解Pull的方式解析Xml。

PULL解析Xml优点:PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。

涉及知识点

  • XmlPullParser 是一个提供对XML进行Pull方式解析的基础功能的接口。
  • xmlPullParser.getEventType()  返回当前节点的事件类型(如:START_TAG, END_TAG, TEXT, etc.)。
  • xmlPullParser.getName() 获取当前节点对应的名称。
  • xmlPullParser.getAttributeCount() 获取当前节点对应的属性个数。
  • xmlPullParser.getText() 获取当前节点对应的文本内容。
  • xmlPullParser.getAttributeName(0) 获取属性对应的名称。
  • xmlPullParser.getAttributeValue(0) 获取属性对应的值。
  • xmlPullParser.next() 移动到下一个事件。

Xml文件

Xml存放相对路径:DemoXml\app\src\main\res\xml\test.xml [xml文件夹]

1 <bookstore> 2     <book category="COOKING"> 3         <title lang="en">Everyday Italiantitle> 4         <author>Giada De Laurentiisauthor> 5         <year>2005year> 6         <price>30.00price> 7     book> 8     <book category="CHILDREN"> 9         <title lang="en">Harry Pottertitle>10         <author>J K. Rowlingauthor>11         <year>2005year>12         <price>29.99price>13     book>14     <book category="WEB">15         <title lang="en">Learning XMLtitle>16         <author>Erik T. Rayauthor>17         <year>2003year>18         <price>39.95price>19     book>20 bookstore>


Xml解析源码

1 /** 2      * 获取Xml内容 3      * @param resources 4      * @param id 5      * @return 6      * @throws XmlPullParserException 7      * @throws IOException 8      */ 9     private Listxml_parser(Resources resources, int id) throws XmlPullParserException, IOException {10         XmlPullParser xmlPullParser = resources.getXml(id);11         ListlstContent=new ArrayList();12         int eventType = xmlPullParser.getEventType();13         while (eventType != XmlPullParser.END_DOCUMENT) {14             switch (eventType) {15                 case XmlPullParser.START_DOCUMENT://文档开始16                     Log.i(TAG, "xml_parser: START_DOCUMENT");17                     break;18                 case XmlPullParser.END_DOCUMENT://文档结束19                     Log.i(TAG, "xml_parser: END_DOCUMENT");20                     break;21                 case XmlPullParser.START_TAG://标记(元素,节点)开始22                     Log.i(TAG, "xml_parser: START_TAG");23                     String tagName = xmlPullParser.getName();24                     //有些节点是没有属性值的,所以需要判断,否则会越界25                     int count = xmlPullParser.getAttributeCount();//获取属性个个数26                     String tagAttributeValue="";27                     String tagAttributeName="";28                     //String text =xmlPullParser.getText();//此处获取不到text29                     String content="";30                     if (count > 0) {31                         tagAttributeName=xmlPullParser.getAttributeName(0);32                         tagAttributeValue = xmlPullParser.getAttributeValue(0);33                         content="标签="+tagName+"属性名="+tagAttributeName+"属性值="+tagAttributeValue;34                     }else{35                         content="标签="+tagName;36                     }37                     lstContent.add(content);38                     break;39                 case XmlPullParser.TEXT:40                     String text =xmlPullParser.getText();41                     lstContent.add("节点内容="+text);42                     break;43                 case XmlPullParser.END_TAG://标记结束44                     Log.i(TAG, "xml_parser: END_TAG");45                     break;46             }47             eventType = xmlPullParser.next();48         }49         return lstContent;50     }


如果Xml文件过大的话,则不适合在Activity主线程中执行,本文是在Worker线程中执行的,如下所示:

1     private static final String TAG="TAG"; 2  3     private static final int MSG_FINISH=0x0001; 4  5     private TextView tvMsg; 6  7     private Handler handler=new Handler(){ 8         @Override 9         public void handleMessage(Message msg) {10             switch (msg.what){11                 case MSG_FINISH:12                     ListlstContent=(List)msg.obj;13                     for (String info :lstContent){14                         tvMsg.append(info+"\r\n");15                     }16                     break;17             }18         }19     };20 21     public void bn_xml_parser_click(View view){22         tvMsg.setText("");23         new Thread(){24             @Override25             public void run() {26                 try {27                     ListlstContent=xml_parser(getResources(),R.xml.test);28                     Message msg=handler.obtainMessage();29                     msg.what=MSG_FINISH;30                     msg.obj=lstContent;31                     handler.sendMessage(msg);32                 } catch (XmlPullParserException e) {33                     e.printStackTrace();34                 } catch (IOException e) {35                     e.printStackTrace();36                 }37             }38         }.start();39     }


JSON解析

Json是一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性。业内主流技术为其提供了完整的解决方案,从而可以在不同平台间进行数据交换。

涉及知识点

  • JSONObject 表示一个Json格式的对象。
  • jsonObject.getString("key"); 获取字符串格式的值。
  • jsonObject.getInt("key"); 获取Int类型的值。
  • jsonObject.getBoolean("key"); 获取bool类型的值。
  • jsonObject.getDouble("key"); 获取浮点数类型的值。
  • jsonObject.get("key"); 返回Object类型的对象。
  • jsonObject.getJSONArray("key"); 返回数据类型的对象。
  • InputStream 输入流。

Json文件

Json存放相对路径:DemoXml\app\src\main\res\raw\test2.json  [raw文件夹]

{
"name": "小明",
"age": 14,
"gender": true,
"height": 1.65,
"grade": null,
"middle_school": "\"W3C\" Middle School",
"skills": [
"JavaScript",
"Java",
"Python",
"Lisp"
]
}


Json解析源码

1   /** 2      * 解析到列表 3      * @return 4      * @throws IOException 5      * @throws JSONException 6      */ 7     private Listjson_parser() throws IOException, JSONException { 8         ListlstContent = new ArrayList(); 9         String data = getContent(getResources(), R.raw.test2);10         JSONObject jsonObject = new JSONObject(data);11         String name = jsonObject.getString("name");12         int age = jsonObject.getInt("age");13         boolean gender = jsonObject.getBoolean("gender");14         double height = jsonObject.getDouble("height");15         Object grade = jsonObject.get("grade");16         String middleSchool = jsonObject.getString("middle_school");17         JSONArray jsonArray = jsonObject.getJSONArray("skills");18         lstContent.add("name=" + name);19         lstContent.add("age=" + age);20         lstContent.add("gender=" + gender);21         lstContent.add("height=" + height);22         lstContent.add("grade=" + grade);23         lstContent.add("middleSchool=" + middleSchool);24         for (int i = 0; i < jsonArray.length(); i++) {25             String skill = jsonArray.getString(i);26             lstContent.add("skill=" + skill);27         }28         return lstContent;29     }30 31     /**32      * 通过id获取Json文件对应的内容33      * @param resources34      * @param id35      * @return36      * @throws IOException37      */38     private String getContent(Resources resources, int id) throws IOException {39         StringBuilder stringBuilder = new StringBuilder();40         InputStream inputStream = null;41         try {42             inputStream = resources.openRawResource(id);43             byte[] bytes = new byte[1024];44             int length = inputStream.read(bytes, 0, 1024);45             while (length > -1) {46                 stringBuilder.append(new String(bytes, 0, length));47                 length = inputStream.read(bytes, 0, 1024);48             }49         } finally {50             if (inputStream != null) {51                 inputStream.close();52             }53         }54         return stringBuilder.toString();55     }


同样,如果Json文件比较大,或者解析比较慢,则不能在Activity主线程中执行,需要新启动一个Worker线程,在后台执行,如下所示:

1     private static final String TAG="TAG"; 2  3     private static final int MSG_FINISH=0x0001; 4  5     private static  final int MSG_SERIALIZE=0x0002; 6  7     private TextView tvMsg; 8  9     private Handler handler=new Handler(){10         @Override11         public void handleMessage(Message msg) {12             switch (msg.what){13                 case MSG_FINISH:14                     ListlstContent=(List)msg.obj;15                     for (String info :lstContent){16                         tvMsg.append(info+"\r\n");17                     }18                     break;19             }20         }21     };22 23     /**24      * 解析Json25      * @param view26      */27     public void bn_json_parser_click(View view) {28         tvMsg.setText("");29         new Thread() {30             @Override31             public void run() {32                 try {33                     ListlstContent = json_parser();34                     Message msg = handler.obtainMessage();35                     msg.what = MSG_FINISH;36                     msg.obj = lstContent;37                     handler.sendMessage(msg);38                 } catch (IOException e) {39                     e.printStackTrace();40                 } catch (JSONException e) {41                     e.printStackTrace();42                 }43             }44         }.start();45     }


如果需要将Json反序列化成类对象,或者将类对象序列化成Json格式文件,如下是一个帮助类:

一起学Android之Xml与Json解析_Json一起学Android之Xml与Json解析_Json

1 package com.hex.demoxml;  2   3 import android.util.Log;  4   5 import java.util.Collection;  6 import java.lang.reflect.Array;  7 import java.lang.reflect.Field;  8 import java.lang.reflect.ParameterizedType;  9 import java.lang.reflect.Type; 10 import java.util.Collection; 11 import org.json.JSONArray; 12 import org.json.JSONException; 13 import org.json.JSONObject; 14 import org.json.JSONStringer; 15  16 /** JSON序列化辅助类 **/ 17 public class JsonHelper { 18     private static final String TAG="TAG"; 19     /** 20      * 将对象转换成Json字符串 21      **/ 22     public static String toJSON(Object obj) { 23         JSONStringer js = new JSONStringer(); 24         serialize(js, obj); 25         return js.toString(); 26     } 27  28     /** 29      * 序列化为JSON 30      **/ 31     private static void serialize(JSONStringer js, Object o) { 32         if (isNull(o)) { 33             try { 34                 js.value(null); 35             } catch (JSONException e) { 36                 e.printStackTrace(); 37             } 38             return; 39         } 40  41         Class clazz = o.getClass(); 42         if (isObject(clazz)) { // 对象 43             serializeObject(js, o); 44         } else if (isArray(clazz)) { // 数组 45             serializeArray(js, o); 46         } else if (isCollection(clazz)) { // 集合 47             Collection collection = (Collection) o; 48             serializeCollect(js, collection); 49         } else { // 单个值 50             try { 51                 js.value(o); 52             } catch (JSONException e) { 53                 e.printStackTrace(); 54             } 55         } 56     } 57  58     /** 59      * 序列化数组 60      **/ 61     private static void serializeArray(JSONStringer js, Object array) { 62         try { 63             js.array(); 64             for (int i = 0; i < Array.getLength(array); ++i) { 65                 Object o = Array.get(array, i); 66                 serialize(js, o); 67             } 68             js.endArray(); 69         } catch (Exception e) { 70             e.printStackTrace(); 71         } 72     } 73  74     /** 75      * 序列化集合 76      **/ 77     private static void serializeCollect(JSONStringer js, Collection collection) { 78         try { 79             js.array(); 80             for (Object o : collection) { 81                 serialize(js, o); 82             } 83             js.endArray(); 84         } catch (Exception e) { 85             e.printStackTrace(); 86         } 87     } 88  89     /** 90      * 序列化对象 91      **/ 92     private static void serializeObject(JSONStringer js, Object obj) { 93         try { 94             js.object(); 95             for (Field f : obj.getClass().getFields()) { 96                 Object o = f.get(obj); 97                 js.key(f.getName()); 98                 serialize(js, o); 99             }100             js.endObject();101         } catch (Exception e) {102             e.printStackTrace();103         }104     }105 106     /**107      * 反序列化简单对象108      *109      * @throws110      **/111     public static T parseObject(JSONObject jo, Class clazz) {112         Log.i(TAG, "parseObject: >>>>>>第二个开始");113         if (clazz == null || isNull(jo)) {114             Log.i(TAG, "parseObject: >>>>>>第二个parseObject");115             return null;116         }117 118         T obj = createInstance(clazz);119         if (obj == null) {120             Log.i(TAG, "parseObject: >>>>>>创建实例为空");121             return null;122         }123         Log.i(TAG, "parseObject: >>>>>>属性长度"+clazz.getFields().length);124         Log.i(TAG, "parseObject: >>>>>>属性长度2"+clazz.getClass());125         for (Field f : clazz.getFields()) {126             Log.i(TAG, "parseObject: >>>>>>"+f.getName());127             setField(obj, f, jo);128             //Log.i(TAG, "parseObject: >>>>>>"+obj.);129         }130         Log.i(TAG, "parseObject: >>>>>返回obj"+obj.getClass());131         return obj;132     }133 134     /**135      * 反序列化简单对象136      *137      * @throws138      **/139     public static T parseObject(String jsonString, Class clazz) {140         if (clazz == null || jsonString == null || jsonString.length() == 0) {141             Log.i(TAG, "parseObject: >>>>>>>null");142             return null;143         }144         Log.i(TAG, "parseObject: >>>>>>>not null");145         JSONObject jo = null;146         try {147             jo = new JSONObject(jsonString);148         } catch (JSONException e) {149             Log.i(TAG, "parseObject: >>>>>>转换json对象异常:"+e.getMessage());150             e.printStackTrace();151         }152 153         if (isNull(jo)) {154             Log.i(TAG, "parseObject: >>>>>转换后为null");155             return null;156         }157         Log.i(TAG, "parseObject: >>>>>>进入下一步");158         return parseObject(jo, clazz);159     }160 161     /**162      * 反序列化数组对象163      *164      * @throws165      **/166     public static T[] parseArray(JSONArray ja, Class clazz) {167         if (clazz == null || isNull(ja)) {168             return null;169         }170 171         int len = ja.length();172         Log.i(TAG, "parseArray: >>>>>"+len);173         Log.i(TAG, "parseArray: >>>>>"+clazz.getName());174         @SuppressWarnings("unchecked")175         T[] array = (T[]) Array.newInstance(clazz, len);176 177         for (int i = 0; i < len; ++i) {178             try {179                 Object object=ja.get(i);180                 if(isSingle(clazz)){181                     Log.i(TAG, "parseArray: >>>>>:"+object.toString());182                     array[i]=(T)object.toString();183                 }else {184                     JSONObject jo = ja.getJSONObject(i);185                     Log.i(TAG, "parseArray: >>>>>jo:"+jo.toString());186                     T o = parseObject(jo, clazz);187                     Log.i(TAG, "parseArray: >>>>>o:" + o.toString());188                     array[i] = o;189                 }190             } catch (JSONException e) {191                 e.printStackTrace();192             }193         }194 195         return array;196     }197 198     /**199      * 反序列化数组对象200      *201      * @throws202      **/203     public static T[] parseArray(String jsonString, Class clazz) {204         if (clazz == null || jsonString == null || jsonString.length() == 0) {205             return null;206         }207         JSONArray jo = null;208         try {209             jo = new JSONArray(jsonString);210         } catch (JSONException e) {211             e.printStackTrace();212         }213 214         if (isNull(jo)) {215             return null;216         }217 218         return parseArray(jo, clazz);219     }220 221     /**222      * 反序列化泛型集合223      *224      * @throws225      **/226     @SuppressWarnings("unchecked")227     public static CollectionparseCollection(JSONArray ja, Class collectionClazz,228                                                     Class genericType) {229 230         if (collectionClazz == null || genericType == null || isNull(ja)) {231             return null;232         }233 234         Collectioncollection = (Collection) createInstance(collectionClazz);235 236         for (int i = 0; i < ja.length(); ++i) {237             try {238                 JSONObject jo = ja.getJSONObject(i);239                 T o = parseObject(jo, genericType);240                 collection.add(o);241             } catch (JSONException e) {242                 e.printStackTrace();243             }244         }245 246         return collection;247     }248 249     /**250      * 反序列化泛型集合251      *252      * @throws253      **/254     public static CollectionparseCollection(String jsonString, Class collectionClazz,255                                                     Class genericType) {256         if (collectionClazz == null || genericType == null || jsonString == null257                 || jsonString.length() == 0) {258             return null;259         }260         JSONArray jo = null;261         try {262             jo = new JSONArray(jsonString);263         } catch (JSONException e) {264             e.printStackTrace();265         }266 267         if (isNull(jo)) {268             return null;269         }270 271         return parseCollection(jo, collectionClazz, genericType);272     }273 274     /**275      * 根据类型创建对象276      **/277     private static T createInstance(Class clazz) {278         if (clazz == null)279             return null;280         T obj = null;281         try {282             obj = clazz.newInstance();283         } catch (Exception e) {284             Log.i(TAG, "createInstance: >>>>>>创建实例异常");285             e.printStackTrace();286         }287         return obj;288     }289 290     /**291      * 设定字段的值292      **/293     private static void setField(Object obj, Field f, JSONObject jo) {294         String name = f.getName();295         Class clazz = f.getType();296         Log.i(TAG, "setField: >>>>>name:"+name);297         try {298             if (isArray(clazz)) { // 数组299                 Log.i(TAG, "setField: >>>>>数组");300                 Class c = clazz.getComponentType();301                 JSONArray ja = jo.optJSONArray(name);302                 if (!isNull(ja)) {303                     Log.i(TAG, "setField: >>>>>ja:"+ja.getString(0));304                     Object array = parseArray(ja, c);305                     f.set(obj, array);306                 }else{307                     Log.i(TAG, "setField: >>>>>数组为空");308                 }309             } else if (isCollection(clazz)) { // 泛型集合310                 Log.i(TAG, "setField: >>>>>泛型集合");311                 // 获取定义的泛型类型312                 Class c = null;313                 Type gType = f.getGenericType();314                 if (gType instanceof ParameterizedType) {315                     ParameterizedType ptype = (ParameterizedType) gType;316                     Type[] targs = ptype.getActualTypeArguments();317                     if (targs != null && targs.length > 0) {318                         Type t = targs[0];319                         c = (Class) t;320                     }321                 }322 323                 JSONArray ja = jo.optJSONArray(name);324                 if (!isNull(ja)) {325                     Object o = parseCollection(ja, clazz, c);326                     f.set(obj, o);327                 }328             } else if (isSingle(clazz)) { // 值类型329                 Log.i(TAG, "setField: >>>>>Single值类型");330                 Object o = jo.opt(name);331                 if (o != null) {332                     f.set(obj, o);333                 }334             } else if (isObject(clazz)) { // 对象335                 Log.i(TAG, "setField: >>>>>Object对象:"+clazz);336                 JSONObject j = jo.optJSONObject(name);337                 if (!isNull(j)) {338 339                     Object o = parseObject(j, clazz);340                     f.set(obj, o);341                 }else{342                     Log.i(TAG, "setField: >>>>>Object对象为null");343                 }344             } else {345                 Log.i(TAG, "setField: >>>>>未知类型:"+clazz);346                 throw new Exception("unknow type!");347             }348         } catch (Exception e) {349             e.printStackTrace();350         }351     }352 353     /**354      * 判断对象是否为空355      **/356     private static boolean isNull(Object obj) {357         if (obj instanceof JSONObject) {358             return JSONObject.NULL.equals(obj);359         }360         return obj == null;361     }362 363     /**364      * 判断是否是值类型365      **/366     private static boolean isSingle(Class clazz) {367         return isBoolean(clazz) || isNumber(clazz) || isString(clazz);368     }369 370     /**371      * 是否布尔值372      **/373     public static boolean isBoolean(Class clazz) {374         return (clazz != null)375                 && ((Boolean.TYPE.isAssignableFrom(clazz)) || (Boolean.class376                 .isAssignableFrom(clazz)));377     }378 379     /**380      * 是否数值381      **/382     public static boolean isNumber(Class clazz) {383         return (clazz != null)384                 && ((Byte.TYPE.isAssignableFrom(clazz)) || (Short.TYPE.isAssignableFrom(clazz))385                 || (Integer.TYPE.isAssignableFrom(clazz))386                 || (Long.TYPE.isAssignableFrom(clazz))387                 || (Float.TYPE.isAssignableFrom(clazz))388                 || (Double.TYPE.isAssignableFrom(clazz)) || (Number.class389                 .isAssignableFrom(clazz)));390     }391 392     /**393      * 判断是否是字符串394      **/395     public static boolean isString(Class clazz) {396         return (clazz != null)397                 && ((String.class.isAssignableFrom(clazz))398                 || (Character.TYPE.isAssignableFrom(clazz)) || (Character.class399                 .isAssignableFrom(clazz)));400     }401 402     /**403      * 判断是否是对象404      **/405     private static boolean isObject(Class clazz) {406         return clazz != null && !isSingle(clazz) && !isArray(clazz) && !isCollection(clazz);407     }408 409     /**410      * 判断是否是数组411      **/412     public static boolean isArray(Class clazz) {413         return clazz != null && clazz.isArray();414     }415 416     /**417      * 判断是否是集合418      **/419     public static boolean isCollection(Class clazz) {420         return clazz != null && Collection.class.isAssignableFrom(clazz);421     }422 }


View Code

备注

沉舟侧畔千帆过,病树前头万木春。