更強的 JsonPath 兼容性及性能測試
最近給自己的json
框架snack3
添加了json path
支持。搞好之后,找了兩個市面上流行框架比較性測試,以助自己改進框架的性能和兼容性。
測了一圈之后,發現snack3
兼容性良好,性能更是最好的。晚上要喝點小酒慶祝一下!!!
免責聲明:我也是個java新手,可能測試得方式不對而造成不科學的結果,可以留言指出來。以下測試數值只對我的電腦有效(配置:Macbook pro 13 2018款 i7+16G+512G)。
Snack3 借簽了 Javascript
所有變量由 var
申明,及 Xml dom
一切都是 Node
的設計。其下一切數據都以ONode
表示,ONode
也即 One node
之意,代表任何類型,也可以轉換為任何類型。
- 強調文檔樹的操控和構建能力
- 做為中間媒體,方便不同格式互轉
- 高性能
Json path
查詢(兼容性和性能很贊) - 支持
序列化、反序列化
本案測試用的三個框架及版本:
- com.alibaba:fastjson:1.2.29
- com.jayway.jsonpath:json-path:2.2.0
- org.noear:snack3:3.1.5.9
三份測試數據樣本:
- A:
{code:1,msg:'Hello world',data:{list:[1,2,3,4,5], ary2:[{a:2},{a:3,b:{c:'ddd'}}]}}
- B:
[{b:{c:1}}, {b:{d:1}}, {b:{c:2}}, {b:{c:23}}]
- C:
[{c:'aaaa'}, {b:'cccc'}, {c:'cccaa'}]
測試方案:
1.測試偽代碼
var text = "...";
//1.預解析json
var obj = JSON.parse(text);
long start = System.currentTimeMillis();
for(int i=0,len=1000000; i<len; i++) {
//2.執行json path
JSONPath.eval(obj,"$...");
}
//3.100萬次的消耗時間(記錄的數值就是這個)
long times = System.currentTimeMillis() - start;
System.out.println(times);
2.每個框架、每個表達式各執行4次,並記錄后3次消耗時間
3.最后制成對比表格
4.測試結果:
Json path表達式 | 數據 | fastjson | json-path | snack3 |
---|---|---|---|---|
$..a |
A | 529,546,539 | 2658,2633,2590 | 225,225,232 |
$..* |
A | (不兼容1) | 3227,3220,3156 | 306,315,325 |
data.list[1,4] |
A | 85,90,86 | 782,798,776 | 133,137,131 |
data.list[1:4] |
A | 105,109,109 | 941,899,947 | 143,145,146 |
data.ary2[1].b.c |
A | 60,58,58 | 929,826,837 | 84,86,80 |
data.ary2[*].b.c |
A | (不兼容2) | 1105,1025,1050 | 173,152,155 |
$..b[?(@.c == 12)] |
B | (不兼容2) | 5628,5739,5636 | 580,535,532 |
$..c.min() |
B | (不兼容2) | (不兼容2) | 279,282,285 |
$[?(@.c =~ /a+/)] |
C | (不兼容2) | 3575,3591,3813 | 444,423,429 |
$..ary2[0].a |
A | 325,321,319 | 2522,2551,2591 | 310,311,314 |
data.list[?(@ in $..ary2[0].a)] |
A | (不兼容2) | 5494,5326,5483 | 678,674,667 |
注:
- 不兼容1 : 直接返回了根節點自己
- 不兼容2 : 直接異常
總結
- fastjson 毫無兼容性可言
- json-path 性能不理想,函數使用局限性大
- snack3 性能最好,支持兩種策略:1.標准模式,保持與json-path兼容效果;2.非標准模式,函數使用余地更大
附1:snack3項目地址:
附2:..及函數表達式的兼容性說明
json-path:(snack3的標准模式同),處理策略如下:
- 選擇器的執行順序:(括號里的表達式處理后再聚合)
$..(ary2[0].a)
$..(c.min())
//如果c不是數組,此處會出錯$..(ary2[0][0])
- 只能:
data.list[?(@ in $..ary2[0].a)]
- 只能:在原數組節點上執行函數
snack3:(snack3的非標准模式),處理策略如下:
-
選擇器的執行順序:(括號里的表達式處理后再聚合)
($..ary2[0]).a
($..c).min()
//c是不是數組都正常 //實際使用中,這種會更方便,同時也兼容其它表達式($..ary2[0])[0]
//這種會引起不同的結果 //不過實際中極少出現
-
可以:
data.list[?(@ in $..ary2[0].a)]
或data.list[?(@ == $..ary2[0].a[0])]
-
可以:在原數組節點上執行函數 或 查詢結果上執行
附3:測試代碼
com.alibaba:fastjson
測試代碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/speed/SpeedFastjsonJsonPathTest.javacom.jayway.jsonpath:json-path
測試代碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/speed/SpeedJaywayJsonPathTest.javaorg.noear:snack3
測試代碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/speed/SpeedJsonPathTest.java