2022年了,重新做了一份json path
的相容性與效能測試。三個市面上流行框架比較性測試。
免責宣告:可能測試得方式不對而造成不科學的結果(另外,機器不同結果會有不同),可以留言指出來。以下測試數值只對我的電腦有效(配置:Macbook pro 13 2020款 i7+32G+1T)。
本案測試用的三個框架及版本:
- com.alibaba.fastjson2:fastjson2:2.0.4
- com.jayway.jsonpath:json-path:2.2.0
- org.noear:snack3:3.2.31
三份測試資料樣本:
- 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表示式 | 資料 | fastjson2 | json-path | snack3 |
---|---|---|---|---|
$..a |
A | 872,764,715 | 2658,2633,2590 | 225,225,232 |
$..* |
A | (不相容1) | 3227,3220,3156 | 306,315,325 |
$.data.list[1,4] |
A | 577,524,419 | 782,798,776 | 133,137,131 |
$.data.list[1:4] |
A | 332,367,391 | 941,899,947 | 143,145,146 |
$.data.ary2[1].a |
A | 315,339,329 | 704,663,655 | 84,86,80 |
$.data.ary2[*].b.c |
A | 642,645,660 | 1105,1025,1050 | 239,235,237 |
$..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 | 735,728,736 | 2522,2551,2591 | 310,311,314 |
$.data.list[?(@ in $..ary2[0].a)] |
A | (不相容2) | 5494,5326,5483 | 678,674,667 |
注:
- 不相容1 : 直接返回空陣列
- 不相容2 : 直接異常
總結
- fastjson2 相容性差了些
- 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.fastjson2:fastjson2
測試程式碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedFastjson2JsonPathTest.javacom.jayway.jsonpath:json-path
測試程式碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedJaywayJsonPathTest.javaorg.noear:snack3
測試程式碼:https://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedJsonPathTest.java