在網路中,數據交互通常是以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