Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

一起学Android之Xml与Json解析

Alan.hsiang 2019-08-03 17:33:00 阅读数:39 评论数:0 点赞数:0 收藏数:0

概述

在网络中,数据交互通常是以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文件夹]

 <bookstore>
     <book category="COOKING">
         <title lang="en">Everyday Italian</title>
         <author>Giada De Laurentiis</author>
         <year>2005</year>
         <price>30.00</price>
     </book>
     <book category="CHILDREN">
         <title lang="en">Harry Potter</title>
         <author>J K. Rowling</author>
         <year>2005</year>
         <price>29.99</price>
     </book>
     <book category="WEB">
         <title lang="en">Learning XML</title>
         <author>Erik T. Ray</author>
         <year>2003</year>
         <price>39.95</price>
     </book>
 </bookstore>

Xml解析源码

 /**
      * 获取Xml内容
      * @param resources
      * @param id
      * @return
      * @throws XmlPullParserException
      * @throws IOException
      */
     private List<String> xml_parser(Resources resources, int id) throws XmlPullParserException, IOException {
         XmlPullParser xmlPullParser = resources.getXml(id);
         List<String> lstContent=new ArrayList<String>();
         int eventType = xmlPullParser.getEventType();
         while (eventType != XmlPullParser.END_DOCUMENT) {
             switch (eventType) {
                 case XmlPullParser.START_DOCUMENT://文档开始
                     Log.i(TAG, "xml_parser: START_DOCUMENT");
                     break;
                 case XmlPullParser.END_DOCUMENT://文档结束
                     Log.i(TAG, "xml_parser: END_DOCUMENT");
                     break;
                 case XmlPullParser.START_TAG://标记(元素,节点)开始
                     Log.i(TAG, "xml_parser: START_TAG");
                     String tagName = xmlPullParser.getName();
                     //有些节点是没有属性值的,所以需要判断,否则会越界
                     int count = xmlPullParser.getAttributeCount();//获取属性个个数
                     String tagAttributeValue="";
                     String tagAttributeName="";
                     //String text =xmlPullParser.getText();//此处获取不到text
                     String content="";
                     if (count > 0) {
                         tagAttributeName=xmlPullParser.getAttributeName(0);
                         tagAttributeValue = xmlPullParser.getAttributeValue(0);
                         content="标签="+tagName+"属性名="+tagAttributeName+"属性值="+tagAttributeValue;
                     }else{
                         content="标签="+tagName;
                     }
                     lstContent.add(content);
                     break;
                 case XmlPullParser.TEXT:
                     String text =xmlPullParser.getText();
                     lstContent.add("节点内容="+text);
                     break;
                 case XmlPullParser.END_TAG://标记结束
                     Log.i(TAG, "xml_parser: END_TAG");
                     break;
             }
             eventType = xmlPullParser.next();
         }
         return lstContent;
     }

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

     private static final String TAG="TAG";
 
     private static final int MSG_FINISH=0x0001;
 
     private TextView tvMsg;
 
     private Handler handler=new Handler(){
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what){
                 case MSG_FINISH:
                     List<String> lstContent=(List<String>)msg.obj;
                     for (String info :lstContent){
                         tvMsg.append(info+"\r\n");
                     }
                     break;
             }
         }
     };
 
     public void bn_xml_parser_click(View view){
         tvMsg.setText("");
         new Thread(){
             @Override
             public void run() {
                 try {
                     List<String> lstContent=xml_parser(getResources(),R.xml.test);
                     Message msg=handler.obtainMessage();
                     msg.what=MSG_FINISH;
                     msg.obj=lstContent;
                     handler.sendMessage(msg);
                 } catch (XmlPullParserException e) {
                     e.printStackTrace();
                 } catch (IOException e) {
                     e.printStackTrace();
                 }
             }
         }.start();
     }

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解析源码

   /**
      * 解析到列表
      * @return
      * @throws IOException
      * @throws JSONException
      */
     private List<String> json_parser() throws IOException, JSONException {
         List<String> lstContent = new ArrayList<String>();
         String data = getContent(getResources(), R.raw.test2);
         JSONObject jsonObject = new JSONObject(data);
         String name = jsonObject.getString("name");
         int age = jsonObject.getInt("age");
         boolean gender = jsonObject.getBoolean("gender");
         double height = jsonObject.getDouble("height");
         Object grade = jsonObject.get("grade");
         String middleSchool = jsonObject.getString("middle_school");
         JSONArray jsonArray = jsonObject.getJSONArray("skills");
         lstContent.add("name=" + name);
         lstContent.add("age=" + age);
         lstContent.add("gender=" + gender);
         lstContent.add("height=" + height);
         lstContent.add("grade=" + grade);
         lstContent.add("middleSchool=" + middleSchool);
         for (int i = 0; i < jsonArray.length(); i++) {
             String skill = jsonArray.getString(i);
             lstContent.add("skill=" + skill);
         }
         return lstContent;
     }
 
     /**
      * 通过id获取Json文件对应的内容
      * @param resources
      * @param id
      * @return
      * @throws IOException
      */
     private String getContent(Resources resources, int id) throws IOException {
         StringBuilder stringBuilder = new StringBuilder();
         InputStream inputStream = null;
         try {
             inputStream = resources.openRawResource(id);
             byte[] bytes = new byte[1024];
             int length = inputStream.read(bytes, 0, 1024);
             while (length > -1) {
                 stringBuilder.append(new String(bytes, 0, length));
                 length = inputStream.read(bytes, 0, 1024);
             }
         } finally {
             if (inputStream != null) {
                 inputStream.close();
             }
         }
         return stringBuilder.toString();
     }

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

     private static final String TAG="TAG";
 
     private static final int MSG_FINISH=0x0001;
 
     private static  final int MSG_SERIALIZE=0x0002;
 
     private TextView tvMsg;
 
     private Handler handler=new Handler(){
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what){
                 case MSG_FINISH:
                     List<String> lstContent=(List<String>)msg.obj;
                     for (String info :lstContent){
                         tvMsg.append(info+"\r\n");
                     }
                     break;
             }
         }
     };
 
     /**
      * 解析Json
      * @param view
      */
     public void bn_json_parser_click(View view) {
         tvMsg.setText("");
         new Thread() {
             @Override
             public void run() {
                 try {
                     List<String> lstContent = json_parser();
                     Message msg = handler.obtainMessage();
                     msg.what = MSG_FINISH;
                     msg.obj = lstContent;
                     handler.sendMessage(msg);
                 } catch (IOException e) {
                     e.printStackTrace();
                 } catch (JSONException e) {
                     e.printStackTrace();
                 }
             }
         }.start();
     }

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

 package com.hex.demoxml;
 
 import android.util.Log;
 
 import java.util.Collection;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Collection;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 import org.json.JSONStringer;
 
 /** JSON序列化辅助类 **/
 public class JsonHelper {
     private static final String TAG="TAG";
     /**
      * 将对象转换成Json字符串
      **/
     public static String toJSON(Object obj) {
         JSONStringer js = new JSONStringer();
         serialize(js, obj);
         return js.toString();
     }
 
     /**
      * 序列化为JSON
      **/
     private static void serialize(JSONStringer js, Object o) {
         if (isNull(o)) {
             try {
                 js.value(null);
             } catch (JSONException e) {
                 e.printStackTrace();
             }
             return;
         }
 
         Class<?> clazz = o.getClass();
         if (isObject(clazz)) { // 对象
             serializeObject(js, o);
         } else if (isArray(clazz)) { // 数组
             serializeArray(js, o);
         } else if (isCollection(clazz)) { // 集合
             Collection<?> collection = (Collection<?>) o;
             serializeCollect(js, collection);
         } else { // 单个值
             try {
                 js.value(o);
             } catch (JSONException e) {
                 e.printStackTrace();
             }
         }
     }
 
     /**
      * 序列化数组
      **/
     private static void serializeArray(JSONStringer js, Object array) {
         try {
             js.array();
             for (int i = 0; i < Array.getLength(array); ++i) {
                 Object o = Array.get(array, i);
                 serialize(js, o);
             }
             js.endArray();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     /**
      * 序列化集合
      **/
     private static void serializeCollect(JSONStringer js, Collection<?> collection) {
         try {
             js.array();
             for (Object o : collection) {
                 serialize(js, o);
             }
             js.endArray();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     /**
      * 序列化对象
      **/
     private static void serializeObject(JSONStringer js, Object obj) {
         try {
             js.object();
             for (Field f : obj.getClass().getFields()) {
                 Object o = f.get(obj);
                 js.key(f.getName());
                 serialize(js, o);
             }
             js.endObject();
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     /**
      * 反序列化简单对象
      *
      * @throws
      **/
     public static <T> T parseObject(JSONObject jo, Class<T> clazz) {
         Log.i(TAG, "parseObject: >>>>>>第二个开始");
         if (clazz == null || isNull(jo)) {
             Log.i(TAG, "parseObject: >>>>>>第二个parseObject");
             return null;
         }
 
         T obj = createInstance(clazz);
         if (obj == null) {
             Log.i(TAG, "parseObject: >>>>>>创建实例为空");
             return null;
         }
         Log.i(TAG, "parseObject: >>>>>>属性长度"+clazz.getFields().length);
         Log.i(TAG, "parseObject: >>>>>>属性长度2"+clazz.getClass());
         for (Field f : clazz.getFields()) {
             Log.i(TAG, "parseObject: >>>>>>"+f.getName());
             setField(obj, f, jo);
             //Log.i(TAG, "parseObject: >>>>>>"+obj.);
         }
         Log.i(TAG, "parseObject: >>>>>返回obj"+obj.getClass());
         return obj;
     }
 
     /**
      * 反序列化简单对象
      *
      * @throws
      **/
     public static <T> T parseObject(String jsonString, Class<T> clazz) {
         if (clazz == null || jsonString == null || jsonString.length() == 0) {
             Log.i(TAG, "parseObject: >>>>>>>null");
             return null;
         }
         Log.i(TAG, "parseObject: >>>>>>>not null");
         JSONObject jo = null;
         try {
             jo = new JSONObject(jsonString);
         } catch (JSONException e) {
             Log.i(TAG, "parseObject: >>>>>>转换json对象异常:"+e.getMessage());
             e.printStackTrace();
         }
 
         if (isNull(jo)) {
             Log.i(TAG, "parseObject: >>>>>转换后为null");
             return null;
         }
         Log.i(TAG, "parseObject: >>>>>>进入下一步");
         return parseObject(jo, clazz);
     }
 
     /**
      * 反序列化数组对象
      *
      * @throws
      **/
     public static <T> T[] parseArray(JSONArray ja, Class<T> clazz) {
         if (clazz == null || isNull(ja)) {
             return null;
         }
 
         int len = ja.length();
         Log.i(TAG, "parseArray: >>>>>"+len);
         Log.i(TAG, "parseArray: >>>>>"+clazz.getName());
         @SuppressWarnings("unchecked")
         T[] array = (T[]) Array.newInstance(clazz, len);
 
         for (int i = 0; i < len; ++i) {
             try {
                 Object object=ja.get(i);
                 if(isSingle(clazz)){
                     Log.i(TAG, "parseArray: >>>>>:"+object.toString());
                     array[i]=(T)object.toString();
                 }else {
                     JSONObject jo = ja.getJSONObject(i);
                     Log.i(TAG, "parseArray: >>>>>jo:"+jo.toString());
                     T o = parseObject(jo, clazz);
                     Log.i(TAG, "parseArray: >>>>>o:" + o.toString());
                     array[i] = o;
                 }
             } catch (JSONException e) {
                 e.printStackTrace();
             }
         }
 
         return array;
     }
 
     /**
      * 反序列化数组对象
      *
      * @throws
      **/
     public static <T> T[] parseArray(String jsonString, Class<T> clazz) {
         if (clazz == null || jsonString == null || jsonString.length() == 0) {
             return null;
         }
         JSONArray jo = null;
         try {
             jo = new JSONArray(jsonString);
         } catch (JSONException e) {
             e.printStackTrace();
         }
 
         if (isNull(jo)) {
             return null;
         }
 
         return parseArray(jo, clazz);
     }
 
     /**
      * 反序列化泛型集合
      *
      * @throws
      **/
     @SuppressWarnings("unchecked")
     public static <T> Collection<T> parseCollection(JSONArray ja, Class<?> collectionClazz,
                                                     Class<T> genericType) {
 
         if (collectionClazz == null || genericType == null || isNull(ja)) {
             return null;
         }
 
         Collection<T> collection = (Collection<T>) createInstance(collectionClazz);
 
         for (int i = 0; i < ja.length(); ++i) {
             try {
                 JSONObject jo = ja.getJSONObject(i);
                 T o = parseObject(jo, genericType);
                 collection.add(o);
             } catch (JSONException e) {
                 e.printStackTrace();
             }
         }
 
         return collection;
     }
 
     /**
      * 反序列化泛型集合
      *
      * @throws
      **/
     public static <T> Collection<T> parseCollection(String jsonString, Class<?> collectionClazz,
                                                     Class<T> genericType) {
         if (collectionClazz == null || genericType == null || jsonString == null
                 || jsonString.length() == 0) {
             return null;
         }
         JSONArray jo = null;
         try {
             jo = new JSONArray(jsonString);
         } catch (JSONException e) {
             e.printStackTrace();
         }
 
         if (isNull(jo)) {
             return null;
         }
 
         return parseCollection(jo, collectionClazz, genericType);
     }
 
     /**
      * 根据类型创建对象
      **/
     private static <T> T createInstance(Class<T> clazz) {
         if (clazz == null)
             return null;
         T obj = null;
         try {
             obj = clazz.newInstance();
         } catch (Exception e) {
             Log.i(TAG, "createInstance: >>>>>>创建实例异常");
             e.printStackTrace();
         }
         return obj;
     }
 
     /**
      * 设定字段的值
      **/
     private static void setField(Object obj, Field f, JSONObject jo) {
         String name = f.getName();
         Class<?> clazz = f.getType();
         Log.i(TAG, "setField: >>>>>name:"+name);
         try {
             if (isArray(clazz)) { // 数组
                 Log.i(TAG, "setField: >>>>>数组");
                 Class<?> c = clazz.getComponentType();
                 JSONArray ja = jo.optJSONArray(name);
                 if (!isNull(ja)) {
                     Log.i(TAG, "setField: >>>>>ja:"+ja.getString(0));
                     Object array = parseArray(ja, c);
                     f.set(obj, array);
                 }else{
                     Log.i(TAG, "setField: >>>>>数组为空");
                 }
             } else if (isCollection(clazz)) { // 泛型集合
                 Log.i(TAG, "setField: >>>>>泛型集合");
                 // 获取定义的泛型类型
                 Class<?> c = null;
                 Type gType = f.getGenericType();
                 if (gType instanceof ParameterizedType) {
                     ParameterizedType ptype = (ParameterizedType) gType;
                     Type[] targs = ptype.getActualTypeArguments();
                     if (targs != null && targs.length > 0) {
                         Type t = targs[0];
                         c = (Class<?>) t;
                     }
                 }
 
                 JSONArray ja = jo.optJSONArray(name);
                 if (!isNull(ja)) {
                     Object o = parseCollection(ja, clazz, c);
                     f.set(obj, o);
                 }
             } else if (isSingle(clazz)) { // 值类型
                 Log.i(TAG, "setField: >>>>>Single值类型");
                 Object o = jo.opt(name);
                 if (o != null) {
                     f.set(obj, o);
                 }
             } else if (isObject(clazz)) { // 对象
                 Log.i(TAG, "setField: >>>>>Object对象:"+clazz);
                 JSONObject j = jo.optJSONObject(name);
                 if (!isNull(j)) {
 
                     Object o = parseObject(j, clazz);
                     f.set(obj, o);
                 }else{
                     Log.i(TAG, "setField: >>>>>Object对象为null");
                 }
             } else {
                 Log.i(TAG, "setField: >>>>>未知类型:"+clazz);
                 throw new Exception("unknow type!");
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
 
     /**
      * 判断对象是否为空
      **/
     private static boolean isNull(Object obj) {
         if (obj instanceof JSONObject) {
             return JSONObject.NULL.equals(obj);
         }
         return obj == null;
     }
 
     /**
      * 判断是否是值类型
      **/
     private static boolean isSingle(Class<?> clazz) {
         return isBoolean(clazz) || isNumber(clazz) || isString(clazz);
     }
 
     /**
      * 是否布尔值
      **/
     public static boolean isBoolean(Class<?> clazz) {
         return (clazz != null)
                 && ((Boolean.TYPE.isAssignableFrom(clazz)) || (Boolean.class
                 .isAssignableFrom(clazz)));
     }
 
     /**
      * 是否数值
      **/
     public static boolean isNumber(Class<?> clazz) {
         return (clazz != null)
                 && ((Byte.TYPE.isAssignableFrom(clazz)) || (Short.TYPE.isAssignableFrom(clazz))
                 || (Integer.TYPE.isAssignableFrom(clazz))
                 || (Long.TYPE.isAssignableFrom(clazz))
                 || (Float.TYPE.isAssignableFrom(clazz))
                 || (Double.TYPE.isAssignableFrom(clazz)) || (Number.class
                 .isAssignableFrom(clazz)));
     }
 
     /**
      * 判断是否是字符串
      **/
     public static boolean isString(Class<?> clazz) {
         return (clazz != null)
                 && ((String.class.isAssignableFrom(clazz))
                 || (Character.TYPE.isAssignableFrom(clazz)) || (Character.class
                 .isAssignableFrom(clazz)));
     }
 
     /**
      * 判断是否是对象
      **/
     private static boolean isObject(Class<?> clazz) {
         return clazz != null && !isSingle(clazz) && !isArray(clazz) && !isCollection(clazz);
     }
 
     /**
      * 判断是否是数组
      **/
     public static boolean isArray(Class<?> clazz) {
         return clazz != null && clazz.isArray();
     }
 
     /**
      * 判断是否是集合
      **/
     public static boolean isCollection(Class<?> clazz) {
         return clazz != null && Collection.class.isAssignableFrom(clazz);
     }
 }
View Code

备注

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

 

版权声明
本文为[Alan.hsiang]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/hsiang/p/11295574.html