欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

一起学Android之Xml与Json解析

程序员文章站 2022-06-04 11:13:53
在网络中,数据交互通常是以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 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 }

备注

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