一起学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 Italian</title>
 4         <author>Giada De Laurentiis</author>
 5         <year>2005</year>
 6         <price>30.00</price>
 7     </book>
 8     <book category="CHILDREN">
 9         <title lang="en">Harry Potter</title>
10         <author>J K. Rowling</author>
11         <year>2005</year>
12         <price>29.99</price>
13     </book>
14     <book category="WEB">
15         <title lang="en">Learning XML</title>
16         <author>Erik T. Ray</author>
17         <year>2003</year>
18         <price>39.95</price>
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 List<String> xml_parser(Resources resources, int id) throws XmlPullParserException, IOException {
10         XmlPullParser xmlPullParser = resources.getXml(id);
11         List<String> lstContent=new ArrayList<String>();
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();//此处获取不到text
29                     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                     List<String> lstContent=(List<String>)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             @Override
25             public void run() {
26                 try {
27                     List<String> lstContent=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 List<String> json_parser() throws IOException, JSONException {
 8         List<String> lstContent = new ArrayList<String>();
 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 resources
34      * @param id
35      * @return
36      * @throws IOException
37      */
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         @Override
11         public void handleMessage(Message msg) {
12             switch (msg.what){
13                 case MSG_FINISH:
14                     List<String> lstContent=(List<String>)msg.obj;
15                     for (String info :lstContent){
16                         tvMsg.append(info+"\r\n");
17                     }
18                     break;
19             }
20         }
21     };
22 
23     /**
24      * 解析Json
25      * @param view
26      */
27     public void bn_json_parser_click(View view) {
28         tvMsg.setText("");
29         new Thread() {
30             @Override
31             public void run() {
32                 try {
33                     List<String> lstContent = 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格式文件,如下是一个帮助类:

  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      * @throws
110      **/
111     public static <T> T parseObject(JSONObject jo, Class<T> 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      * @throws
138      **/
139     public static <T> T parseObject(String jsonString, Class<T> 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      * @throws
165      **/
166     public static <T> T[] parseArray(JSONArray ja, Class<T> 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      * @throws
202      **/
203     public static <T> T[] parseArray(String jsonString, Class<T> 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      * @throws
225      **/
226     @SuppressWarnings("unchecked")
227     public static <T> Collection<T> parseCollection(JSONArray ja, Class<?> collectionClazz,
228                                                     Class<T> genericType) {
229 
230         if (collectionClazz == null || genericType == null || isNull(ja)) {
231             return null;
232         }
233 
234         Collection<T> collection = (Collection<T>) 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      * @throws
253      **/
254     public static <T> Collection<T> parseCollection(String jsonString, Class<?> collectionClazz,
255                                                     Class<T> genericType) {
256         if (collectionClazz == null || genericType == null || jsonString == null
257                 || 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> T createInstance(Class<T> 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.class
376                 .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.class
389                 .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.class
399                 .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

备注

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

 

posted @ 2019-08-03 17:33  老码识途呀  阅读(1726)  评论(0编辑  收藏  举报