问题背景
我们在实际的开发过程中有时会遇见需要处理很复杂的JSON数据的情况。一个JSON可能嵌套了多层的JSON数据,也有可能直接包含了一个JSON的数组数据。而直接使用JSONObject的parseObject将其转换为JSONArray又会出现不支持的问题。自己通过解析JSON生成实体又发现实体过多,一下子生成了十几个实体,一个实体只有两三个属性,造成冗余。那这种情况有什么好的处理方案呢?
解决方案
问题一:复杂JSON数据
举例我们要处理一个如下的JSON数据:
{
"collection": {
"native": {
"switch": true,
"lifecycle": 0,
"threshold": 0
},
"appstart": {
"switch": true,
"start": 0
},
"battery": {
"switch": true,
"time": 3000,
"interval": 100,
"count": 1,
"interval": 30000
},
"memory": {
"switch": true,
"time": 1500,
"interval": 100,
"count": 1,
"interval": 30000
},
"memory2": {
"switch": true,
"time": 1500,
"interval": 100,
"count": 1,
"interval": 30000
},
"net": {
"switch": true,
"regex": "",
"target": ""
},
"web": {
"switch": true
},
"picture": {
"switch": true
},
"offcache": {
"switch": true
},
"api": {
"switch": true
},
"blank": {
"switch": true
}
},
"report": {
"strategy": 1,
"upload": 100,
"WIFI": false,
"time": 259200000,
"onstart": false
},
"others": {
"time": 1800000
}
}
有兴趣的同学可以去一些工具里面生成一下里面的实体,会发现里面极其复杂,而这时候我们却需要将接下来的JSON通过和基础模版JSON参数比对,存在则用最新的数据,不存在的key则用基础模版参数的value并将其加入。最后产出JSON。
如果我们用通用方法,将JSON转化为实体然后再比对判空存入。一套下来不仅繁琐,而且容易出错。所以我们之间采用JSONObject的之间的相互转化,用深拷贝的方式进行复制。
思路即是,通过keySet的方式遍历JSON的key值然后根据拿到的key值去获取value,然后根据获取到的value值判断是否有下一层的JSON。如果有则进行递归操作,最终获取到最顶层的value,再进行处理。
这是一个模版的解决方法,大家可以根据自己需求稍做改动。
private JSONObject deepMerge(JSONObject source, JSONObject target) throws JSONException {
for (String key : source.keySet()) {
Object value = source.get(key);
if (!target.containsKey(key)) {
target.put(key, value);
} else {
if (value instanceof JSONObject) {
JSONObject valueJson = (JSONObject) value;
deepMerge(valueJson, target.getJSONObject(key));
} else {
target.put(key, value);
}
}
}
return target;
}
问题二:JSON中存在数组
这个就比较直白了,就是JSON中存在一个数据,数据里面还可能有嵌套的JSON。下面还是来个例子给大家:
{
"msg": "success",
"code": 0,
"data": {
"results": [
{
"value": {
"result": ""
},
"key": "19"
},
{
"value": {
"result": ""
},
"key": "18"
},
{
"value": {
"result": ""
},
"key": "17"
},
{
"value": {
"result": "default",
"params": ""
},
"key": "16"
}
]
}
可以看到这个JSON里面不仅有数组,数组里面还会嵌套一个JSON,这样的JSON解析其他大家会遇到一个JSONArray和JSONObject无法互通的问题即下面这个错误:
com.alibaba.fastjson.JSONArray cannot be cast to com.alibaba.fastjson.JSONObject
而使用JSONArray转换却发现过程中很多方法还紧紧依赖着JSONObject,使用实体又会冗余。这时候我们该怎么办呢。
大体思路就是:通过JSONObject将复杂的JSON进行逐层解析,遇到数组的时候就用JSONArray拿下来,里面具体的数据再使用JSONObject获取。大体模版如下:
JSONObject result = JSONObject.parseObject(result);
if (Integer.parseInt(String.valueOf(result.get("code"))) == 0){
JSONObject abData = result.getJSONObject("data");
JSONArray tmp = JSONArray.parseArray(String.valueOf(abData.get("results")));
for (int i = 0; i < tmp.size(); i++) {
JSONObject tmpResult = tmp.getJSONObject(i);
JSONObject tmpValue = tmpResult.getJSONObject("value");
if (tmpValue.containsKey("params")){
JSONObject tmpParams = tmpValue.getJSONObject("params");
if (Integer.parseInt(String.valueOf(tmpParams.get("panduan"))) >= 14){
panduan = Integer.parseInt(String.valueOf(tmpParams.get("panduan")));
shuju1 = String.valueOf(tmpParams.get("shuju1"));
shuju2 = String.valueOf(String.valueOf(tmpParams.get("shuju2")));
}
}
}
}
总结
我们在处理实际问题的时候应当多尝试新方法,努力突破自我,积累新知识,在工作中获得新的技术。