目前Android和ios应用与网络交互使用得最多的是json数据协议,json轻快的特点十分适合移动平台,因此已逐渐取代了xml,下面来看两个常见的json格式:
{
"code":"10000",
"message":"Login ok",
"result":{
"User":{
"id":1,
"name":"james",
"sign":"just do it"
}
}
}
{
"code":"10000",
"message":"Get weibo list ok",
"result":{
"Weibo.list":[
{
"id":2,
"author":"zhuge",
"content":"weibo content 2"
},
{
"id":1,
"author":"zhuge",
"content":"weibo content 1"
}
]
}
}
两种格式的结构一致,唯一不同的是result字段,前者result字段中是一个JSONObject,常用于返回一些普通的信息,后者是JSONArray,长用与返回一些列表数据。
首先先来说最常规最普通的解析方式,定义两个实体,一个叫User,一个叫Weibo,请一目十行地扫过。
package com.zhuge.jsonparse;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class User extends BaseModel {
private String id;
private String name;
private String sign;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", sign=" + sign + "]";
}
public static HashMap<String, Object> parseUserInfo(String jsonStr) {
HashMap<String, Object> result = new HashMap<String, Object>();
User user = new User();
try {
JSONObject apiJson = new JSONObject(jsonStr);
result.put("code", apiJson.getString("code"));
result.put("message", apiJson.getString("message"));
JSONObject resultJson = apiJson.getJSONObject("result").getJSONObject("User");
user.setId(resultJson.getString("id"));
user.setName(resultJson.getString("name"));
user.setSign(resultJson.getString("sign"));
result.put("result", user);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
package com.zhuge.jsonparse;
import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public class Weibo extends BaseModel {
private String id;
private String author;
private String content;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Weibo [id=" + id + ", author=" + author + ", content="
+ content + "]";
}
public static HashMap<String, Object> parseWeiboList(String jsonStr) {
HashMap<String, Object> result = new HashMap<String, Object>();
ArrayList<Weibo> lstWeibo = new ArrayList<Weibo>();
try {
JSONObject apiJson = new JSONObject(jsonStr);
result.put("code", apiJson.getString("code"));
result.put("message", apiJson.getString("message"));
JSONObject resultJson = apiJson.getJSONObject("result");
JSONArray resultArray = resultJson.getJSONArray("Weibo.list");
for (int i = 0; i < resultArray.length(); i++) {
JSONObject weiboJson = resultArray.getJSONObject(i);
Weibo weibo = new Weibo();
weibo.setId(weiboJson.getString("id"));
weibo.setAuthor(weiboJson.getString("author"));
weibo.setContent(weiboJson.getString("content"));
lstWeibo.add(weibo);
}
result.put("result", lstWeibo);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
两个实体都继承自BaseModel,而BaseModel只是个空类,里面什么也没有定义,虽然是个空类,但也必须继承,为我们后面的通用性做准备。User和Weibo两个实体类中分别定义了三个简单的属性,然后是一些自动生成的get和set方法,最后就是对json数据解析与数据封装的静态方法。这种解析方式通用性不强,每定义一个实体类都要单独针对其做解析,这显然不是我们想要的方式,作为一名程序猿不会“偷懒”那就只能加班!
好了,下面我们来看看本文的重点,打造一个通用的json数据解析框架,只要是按照上面的json协议定义的数据格式(当然你也可以用自己的格式,修改相应代码就好了),简简单单搞定所有的实体类解析:
package com.zhuge.jsonparse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
/**
* JSON通用解析框架
* @author zhugeheng
*
*/
public class ApiResult {
private String code;
private String message;
private Map<String, BaseModel> resultMap;
private Map<String, ArrayList<? extends BaseModel>> resultList;
public ApiResult () {
this.resultMap = new HashMap<String, BaseModel>();
this.resultList = new HashMap<String, ArrayList<? extends BaseModel>>();
}
public String getCode () {
return this.code;
}
public void setCode (String code) {
this.code = code;
}
public String getMessage () {
return this.message;
}
public void setMessage (String message) {
this.message = message;
}
/**
* 获取对象实体
* @param modelName
* @return
* @throws Exception
*/
public Object getModel (String modelName) throws Exception {
Object model = this.resultMap.get(modelName);
if (model == null) {
throw new Exception("Result map is empty");
}
return model;
}
/**
* 获取对象实体列表
* @param modelName
* @return
* @throws Exception
*/
public ArrayList<? extends BaseModel> getModelList (String modelName) throws Exception {
ArrayList<? extends BaseModel> modelList = this.resultList.get(modelName);
if (modelList == null || modelList.size() == 0) {
throw new Exception("Result list is empty");
}
return modelList;
}
/**
* 获取ApiResult实体
* @param jsonStr
* @return
* @throws Exception
*/
public ApiResult getApiResult(String jsonStr) throws Exception {
ApiResult apiResult = new ApiResult();
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(jsonStr);
if (jsonObject != null) {
apiResult.setCode(jsonObject.getString("code"));
apiResult.setMessage(jsonObject.getString("message"));
apiResult.setResult(jsonObject.getString("result"));
}
} catch (JSONException e) {
throw new Exception("Json format error");
} catch (Exception e) {
e.printStackTrace();
}
return apiResult;
}
/**
* 解析Result字段的内容
* @param result
* @throws Exception
*/
@SuppressWarnings("unchecked")
private void setResult (String result) throws Exception {
if (result.length() > 0) {
JSONObject jsonObject = new JSONObject(result);
Iterator<String> it = jsonObject.keys();
while (it.hasNext()) {
String jsonKey = it.next();
String modelName = getModelName(jsonKey);
//实体类所在绝对路径(包名+类名)
String modelClassName = "com.zhuge.jsonparse.model." + modelName;
Log.d("ApiResult", "json key:" + jsonKey + ",model class name:" + modelClassName);
//默认以Array处理
JSONArray modelJsonArray = jsonObject.optJSONArray(jsonKey);
if (modelJsonArray == null) {
//不是Array,那么就是一个普通的Object,如User类
JSONObject modelJsonObject = jsonObject.optJSONObject(jsonKey);
if (modelJsonObject == null) {
throw new Exception("json result is invalid");
}
//将JSONObject转换为Model类并保存结果到Map中
this.resultMap.put(modelName, json2model(modelClassName, modelJsonObject));
} else {
//是Array,如Weibo类
ArrayList<BaseModel> modelList = new ArrayList<BaseModel>();
for (int i = 0; i < modelJsonArray.length(); i++) {
JSONObject modelJsonObject = modelJsonArray.optJSONObject(i);
//将JSONObject转换为Model类并添加到List中
modelList.add(json2model(modelClassName, modelJsonObject));
}
//添加结果列表到Map中
this.resultList.put(modelName, modelList);
}
}
}
}
/**
* 将JSON对象转换为实体对象
* @param modelClassName 实体类所在绝对路径(包名+类名),大小写敏感
* @param modelJsonObject “result”字段中的内容
* @return
* @throws Exception
*/
@SuppressWarnings("unchecked")
private BaseModel json2model (String modelClassName, JSONObject modelJsonObject) throws Exception {
BaseModel modelObj = (BaseModel) Class.forName(modelClassName).newInstance();
//获取实体类
Class<? extends BaseModel> modelClass = modelObj.getClass();
//获取该实体类所有的属性集合
Iterator<String> it = modelJsonObject.keys();
while (it.hasNext()) {
//属性名称
String varField = it.next();
//解析属性值
String varValue = modelJsonObject.getString(varField);
Log.d("ApiResult", "field:" + varField + " value:" + varValue);
//生成属性封装对象
Field field = modelClass.getDeclaredField(varField);
//设置可访问私有属性
field.setAccessible(true);
//将modelObj对象的field属性的值设为解析得到的值
field.set(modelObj, varValue);
}
return modelObj;
}
/**
* 去掉返回结果的“list”
* @param str
* @return
*/
private String getModelName (String str) {
String[] strArr = str.split("\\W");
if (strArr.length > 0) {
str = strArr[0];
}
return str;
}
}
请重点关注
setResult和
json2Model方法,另外getMode方法用于获取一个普通的实体对象如User,getModeList方法用于获取实体对象列表如WeiboList,二者对外暴露。关键代码都有详细的注释,比较好理解,这里就不再啰嗦了。然后你就可以干掉User和Weibo类中的
package com.zhuge.jsonparse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView tvResult = (TextView) findViewById(R.id.tv_result);
findViewById(R.id.btn_obj).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
String jsonStr = readAssetsFile("user.json");
try {
// HashMap<String, Object> result = User.parseUserInfo(jsonStr);
// User user = (User)result.get("result");
ApiResult result = new ApiResult().getApiResult(jsonStr);
User user = (User)result.getModel("User");
tvResult.setText(user.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
});
findViewById(R.id.btn_array).setOnClickListener(new OnClickListener() {
@SuppressWarnings("unchecked")
@Override
public void onClick(View arg0) {
String jsonStr = readAssetsFile("weibo.json");
try {
// HashMap<String, Object> result = Weibo.parseWeiboList(jsonStr);
// ArrayList<Weibo> lstWeibo = (ArrayList<Weibo>)result.get("result");
ApiResult result = new ApiResult().getApiResult(jsonStr);
ArrayList<Weibo> lstWeibo = (ArrayList<Weibo>)result.getModelList("Weibo");
String str = "";
for(Weibo weibo : lstWeibo) {
str += weibo.toString() + "\n";
}
tvResult.setText(str);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* 读取assets文件夹中的内容(测试json字符串)
* @param fileName
* @return
*/
private String readAssetsFile(String fileName) {
try {
InputStream is = getAssets().open(fileName);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
String result = new String(buffer, "UTF-8");
return result;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
该Activity很简单,有两个Button,第一个点击后解析User,第二个点击后解析Weibo List,然后在TextView中将实体用toString方法打印出来。另外,一般我们的json数据都是从网络服务器获取的,本例为了演示方便将json文件放在了assets文件夹中然后直接读取(网络获取数据也不是本文的重点)。OK,一个通用性比较强的解析框架搞定了,然后你就可以跟解析json数据这种体力活say goodbye了!
尊重原创,转载请注明出处:http://blog.csdn.net/zhugehengheng/article/details/45250553