概述

在网络中,数据交互通常是以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);
}
}

备注

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

一起学Android之Xml与Json解析的更多相关文章

  1. Android基础总结(12)——XML和JSON解析

    XML和JSON解析 在网络上传输数据时最常用的格式有两种:XML和JSON.本文主要就是学习如何对这两种常用的数据格式进行解析. 1.XML和JSON的定义 XML:扩展标记语言 (Extensib ...

  2. android基础---->XMl数据的解析

    在网络上传输数据时最常用的格式有两种,XML和JSON,下面首先学一下如何解析XML格式的数据,JSON的解析可以参见我的博客(android基础---->JSON数据的解析).解析XML 格式 ...

  3. Qt on Android: http下载与Json解析

    百度提供有查询 ip 归属地的开放接口,当你在搜索框中输入一个 ip 地址进行搜索,就会打开由 ip138 提供的百度框应用,你能够在框内直接输入 ip 地址查询.我查看了页面请求,提取出查询 ip ...

  4. XML与JSON解析

    [XML简介] XML在线校验工具: http://tool.oschina.net/codeformat/xml 可扩展标记语言(EXtensible Markup Language) 一种标记语言 ...

  5. Android之XML序列化和解析

    XML文件是一种常用的文件格式,可以用来存储与传递数据 ,本文是XML文件序列化与解析的一个简单示例 写文件到本地,并用XML格式存储 /** * 写xml文件到本地 */ private void ...

  6. python入门(十):XML和JSON解析

    一.python解析XML 1.xml.dom.*模块,它是W3C DOM API的实现,若需要处理DOM API则该模块很适合,注意xml.dom包里面有许多模块,须区分它们间的不同: 2.xml. ...

  7. golang的xml、json解析

    xml golang的xml处理主要应用Unmarshal.Marshal方法实现,解析一个xml到struct如下,首先是xml文件: <?xml version="1.0" ...

  8. 【Android】XML文件的解析

    1.首先我们可以在res包路径下创建一个raw包,然后在raw下创建一个email.xml 文件,并修改其内容如下: <?xml version="1.0" encoding ...

  9. android AndroidManifest.xml 属性详细解析

    一.关于AndroidManifest.xml AndroidManifest.xml 是每个android程序中必须的文件.它位于整个项目的根目录,描述了package中暴露的组件(activiti ...

随机推荐

  1. 解决zabbix监控因php问题导致图形界面中文乱码方法

    解决因编译php中添加了-enable-gd-jis-conv选项导致Zabbix监控系统图形界面中文乱码问题 现象: php编译参数: 说明: 如果PHP编译时启用–enable-gd-jis-co ...

  2. Django的Form验证

    Django的Form验证 Form验证:Form提交Form表单数据验证 针对Form提交的数据进行验证 创建模板 class loginForm() 请求提交给模板,创建对象 obj=loginF ...

  3. 3.Redux学习3----redux-saga

    redux-saga和redux-thunk功能差不多,都是为了避免直接在组件生命周期函数中做异步操作,便于自动化测试,便于拆分管理. 首先要下包 npm i redux-saga 第零步:在acti ...

  4. gitlab如何从Github导入项目

    本文简单演示如何Github上导入项目到私人搭建的Gitlab中,搭建过程参考:CentOS7 搭建gitlab服务器. Gitlab版本是gitlab-ce-12.0.2,界面可能稍有差异,但应该影 ...

  5. IT兄弟连 HTML5教程 W3C盒子模型

    日常生活中所见的盒子也就是能装东西的一种箱子,如果家里的东西很多,那么就需要按类别装到不同的箱子中.网页中的内容表现也是一样的,如果页面内容比较多,又想让页面更整洁.更美观.有很好的用户体验,则也需要 ...

  6. Go 开发关键技术指南 | 为什么你要选择 GO?(内含超全知识大图)

    作者 | 杨成立(忘篱) 阿里巴巴高级技术专家 关注"阿里巴巴云原生"公众号,回复 Go 即可查看清晰知识大图! 导读:从问题本身出发,不局限于 Go 语言,探讨服务器中常常遇到的 ...

  7. Java对象 POJO和JavaBean的区别

    转载自https://www.jianshu.com/p/224489dfdec8 这篇博客很通俗易懂的讲明白了什么是POJO,对于刚开始学开发做java项目的菜鸟来说,很有帮助,网课老师是不会讲这些 ...

  8. feign使用hystrix熔断的配置

    熔断器hystrix 在分布式系统中,每个服务都可能会调用很多其他服务,被调用的那些服务就是依赖服务,有的时候某些依赖服务出现故障也是很正常的. Hystrix 可以让我们在分布式系统中对服务间的调用 ...

  9. 解决Maven无法下载fastdfs-client-java依赖

    异常信息:Missing artifact org.csource:fastdfs-client-java:jar:1.27-SNAPSHOT 解决方案:jar包在Maven的中央仓库中缺失,需要手动 ...

  10. python 基础学习笔记(6)--函数(1)

    ## **函数(1)** **函数的定义:** 1. [ ] 小时候大家应该都玩过乐高积木,只要通过想象和创意,可以用它怕拼凑出很多神奇的东西.随着学习的深入,编写的代码日益增加并且越来越复杂,所以需 ...