欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新

一起学Android之Xml与Json解析,

来源: 开发者 投稿于  被查看 6940 次 评论:111

一起学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

备注

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

 

相关文章

    暂无相关文章

用户评论