目前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