更強的 JsonPath 相容性及效能測試之2022版(Snack3,Fastjson2,jayway.jsonpath)

手上寫著程式碼發表於2022-07-04

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的標準模式同),處理策略如下:
  1. 選擇器的執行順序:(括號裡的表示式處理後再聚合)
    • $..(ary2[0].a)
    • $..(c.min()) //如果c不是陣列,此處會出錯
    • $..(ary2[0][0])
  2. 只能:data.list[?(@ in $..ary2[0].a)]
  3. 只能:在原陣列節點上執行函式
snack3:(snack3的非標準模式),處理策略如下:
  1. 選擇器的執行順序:(括號裡的表示式處理後再聚合)

    • ($..ary2[0]).a
    • ($..c).min() //c是不是陣列都正常 //實際使用中,這種會更方便,同時也相容其它表示式
    • ($..ary2[0])[0] //這種會引起不同的結果 //不過實際中極少出現
  2. 可以:data.list[?(@ in $..ary2[0].a)]data.list[?(@ == $..ary2[0].a[0])]

  3. 可以:在原陣列節點上執行函式 或 查詢結果上執行

附3:測試程式碼

相關文章