更強的 JsonPath 兼容性及性能測試之2022版(Snack3,Fastjson2,jayway.jsonpath)
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
測試代碼://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedFastjson2JsonPathTest.javacom.jayway.jsonpath:json-path
測試代碼://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedJaywayJsonPathTest.javaorg.noear:snack3
測試代碼://gitee.com/noear/snack3/blob/master/snack3_demo/src/test/java/benchmark/jsonpath/SpeedJsonPathTest.java