市面上90%的解析器,都是逐个字符解析,然后判断是什么内容,解析成什么类型
这种方式无疑会有一种问题,就是解析器会把你不需要的JSON数据,同样处理一遍。
为此,笔者发现了另外一种思路。
例如下面一段JSON:
{
"d": [{
"__type": "MdoCommonWs.WsStructures.WsWmsLookupResult",
"CallResult": {
"Id": 0,
"Data": null,
"ErrorId": 0,
"ErrorDescription": null
},
"Article": {
"Id": "001",
"Description": "ANKERMECHANISCH",
"Unit": "pieces",
"UnitPrice": 7,
"MinStock": 0,
"MaxStock": 0,
"Info": "ANKERMECHANISCHM12",
"Photo": [],
"PhotoUrl": "",
"WeightUnit": "kg",
"Weight": 0.05,
"CountStock": 0
},
"Locations": [{
"LocationId": "00.00.AA.01.01.01.02",
"Type": 0,
"IsBlocked": false,
"ArticleId": "001",
"Stock": 2,
"TotalStock": 2,
"LastActionDate": "/Date(1480334382093)/",
"LastInventoryDate": "/Date(1480334319527)/"
}]
}],
"s": [1, 2, 3]
}
怎么样,是不是很复杂。如果它变成下面的JSON后呢?
{
"d": #aaaaa,
"s": #bbbbb
}
没错,你一眼就能看出来这是一个object,然后用逗号分隔一下,很容易就能获取两个键值对。分别是d:#aaaaa和s:#bbbbb,这样你在获取d的对象时,再去解析d的内容就行了,根本不用去管s是什么。
笔者的方法,就是先把JSON里面的对象({})和数组([])全部替换掉,这样就能得到一个最简单的对象或数组。而那些被替换的内容,只要缓存起来就行,解析的时候再取出来就可以了。
下面是核心的替换代码:
/**
* 将json字符串转成块 例{"userid":[1,2,3]}会被转成{"userid":#1669281915687}
*
* @param temp
* 原始json
* @param c1
* 块的起始位置
* @param c2
* 块的终止位置
*/
private void replaceJSONBlock(final StringBuffer temp, String c1, String c2) {
int left = temp.lastIndexOf(c1);
if (left > -1) {
int right = temp.indexOf(c2, left);
if (right > -1) {
String uniqueKey = JSON.CACHE_PREFIX + System.nanoTime();
this.cacheMap.put(uniqueKey, temp.substring(left, right + 1));
temp.replace(left, right + 1, uniqueKey);
replaceJSONBlock(temp, c1, c2);
}
}
}
这样之后,这个JSON就可以很简单的进行处理了,甚至可以支持最新的JSON5规范。
测试:
long s = System.currentTimeMillis();
System.out.println(
"self: " + obj.getJSONArray("d").getJSONObject(0).getJSONObject("CallResult").getString("Data"));
System.out.println("self: " + obj.getJSONArray("d").toJSONString());
System.out.println("self: " + obj.getJSONArray("s").get(1));
long s1 = System.currentTimeMillis();
System.out.println("time:" + (s1 - s));
com.alibaba.fastjson.JSONObject obj2 = com.alibaba.fastjson.JSON.parseObject(str);
System.out.println(
"ali: " + obj2.getJSONArray("d").getJSONObject(0).getJSONObject("CallResult").getString("Data"));
System.out.println("ali: " + obj2.getJSONArray("d").toJSONString());
System.out.println("ali: " + obj2.getJSONArray("s").get(1));
long s2 = System.currentTimeMillis();
System.out.println("time:" + (s2 - s1));
结果:
self: null
self: [{"__type":"MdoCommonWs.WsStructures.WsWmsLookupResult","CallResult":{"Id":0,"Data":null,"ErrorId":0,"ErrorDescription":null},"Article":{"Id":"001","Description":"ANKER M12 MECHANISCH","Unit":"pieces","UnitPrice":7,"MinStock":0,"MaxStock":0,"Info":"ANKER MECHANISCH M12","Photo":[],"PhotoUrl":"","WeightUnit":"kg","Weight":0.05,"CountStock":0},"Locations":[{"LocationId":"00.00.AA.01.01.01.02","Type":0,"IsBlocked":false,"ArticleId":"001","Stock":2,"TotalStock":2,"LastActionDate":"/Date(1480334382093)/","LastInventoryDate":"/Date(1480334319527)/"}]}]
self: 2
time:15
ali: null
ali: [{"CallResult":{"ErrorId":0,"Id":0},"__type":"MdoCommonWs.WsStructures.WsWmsLookupResult","Article":{"MinStock":0,"UnitPrice":7,"CountStock":0,"Description":"ANKER\t\t M12\t\t MECHANISCH","MaxStock":0,"WeightUnit":"kg","Photo":[],"Id":"001","PhotoUrl":"","Unit":"pieces","Info":"ANKER\t\t MECHANISCH\t\t M12","Weight":0.05},"Locations":[{"Type":0,"LocationId":"00.00.AA.01.01.01.02","ArticleId":"001","LastInventoryDate":"/Date(1480334319527)/","LastActionDate":"/Date(1480334382093)/","IsBlocked":false,"Stock":2,"TotalStock":2}]}]
ali: 2
time:207
对此,你有什么看法呢?