超級靈活的 Java JSON 庫

不是已經有 objectMapper.readValue 了嗎?為什么還需要一個新的 JSON 庫呢?因為我發現下面這幾個場合已有的庫無法滿足我的需求, 所以發明了 jsoniter (json-iterator):

  • 和 PHP 打交道: 如果你要的是 int,他們可能給你 100 也可能給你 "100"。如果你要的是對象,他們在空值的時候可能給你個 []。

  • 處理大量的 JSON:解析大量的 JSON,但是只是從中提取少量的信息

  • 無法直接綁定到對象上:JSON自身是 key/value 的形式,和對象模型沒法直接綁定上

除了靈活之外 jsoniter 還比現有的庫快很多(比如 jackson,gson,fastjson 這些),歡迎第三方來做公正客觀的性能評測。這是我自測 1kb json 數據綁定的結果

jsoniter 的獨特之處源自創新:

  • Any 數據類型把原始的 byte 數組保存為 Any 對象。只有在用到的時候才會延遲去做解析。而且 Any 還是當成 PHP array 或者 Javascript object 那樣來使用,不用關心類型轉換問題。

  • Iterator 的抽象把 JSON 輸入流包裝為類似 iterator 的對象。你可以用流式解析地方式遍歷整個 JSON 里的對象圖,就和遍歷內存里的集合對象一樣方便。類似 gson 的流式 api,但是更簡單。

  • Trie-treeJSON 最大的缺點(也是最強大之處)在于其對象的字段是字符串。數據綁定的時候比較字符串非常耗費時間。jsoniter 使用 tri-tree 的方式來提高性能。

  • 靈活的代碼生成所有的 decoder/encoder 的邏輯都可以代碼生成。并且提供了反射,動態代碼生成和靜態代碼生成三種方式,Java 的各種平臺均可用。

  • 只為自己所需的功能付出代價以 InputStream 作為輸入的時候,比 byte[] 要慢。傳統的解析器使用繼承或者功能開關的方式來做抽象的實現,但是這對于性能來說是有損的。jsoniter 使用動態代碼生成來實現 class shadowing,從而實現無損的切換。

  • 校驗必填字段主流的 JSON 解析器都沒有實現必填字段檢查的功能。當你看到一個int是0的時候,不知道是 JSON 里的值是0,還是上游沒有把這個字段傳過來。jsoniter 使用了 bit 位來跟蹤每一個必填字段,效率很高。

雖然做了很多工作來確保 jsoniter 是最快的。但是大部分人其實只要有一個東西能幫他們把事情搞定就好了。來一個例子展示 api 是多么的靈活,也許更有意義:

[1024, {"product_id": 100, "start": "beijing"}]["1025", {"product_id": 101, "start": "shanghai"}]// many many more lines

每行是代表一個訂單。第一個元素是訂單id,第二個元素是訂單詳情。值得注意之處有以下幾點:

  • 行數可能很多,一次性讀進來內存壓力很大

  • 某些行的訂單id是 int,某些行的訂單id是 string。這在和 PHP 交互的時候經常發生。

  • 訂單詳情有很多字段,手工讀取很麻煩,需要對象綁定

只需要 6 行代碼,以上所有問題都可以解決:

JsonIterator iter = JsonIterator.parse(input); // input streamOrderDetails orderDetails = new OrderDetails(); // reusedwhile(iter.whatIsNext() != ValueType.INVALID) {
    Any order = iter.readAny(); // lazy
    int orderId = order.toInt(0); // weakly typed
    String start = order.get(1).bindTo(orderDetails).start; // data binding}
  • JsonIterator.parse 以 InputStream 作為輸入,所有解析都是流式處理的

  • readAny 返回了 Any 類型的對象。實際的解析只有在取成員字段的時候才發生。用起來簡單,而且速度快。

  • bindTo(orderDetails),不僅僅支持對象綁定,甚至可以綁定到已有對象上避免分配內存

jsoniter 在普通的序列化,反序列化的場景下也很好使,就一行。

JsonStream.serialize(new int[]{1,2,3})JsonIterator.deserialize("[1,2,3]", int[].class)

jsoniter 不強迫你使用任何一種風格,可以在數據綁定,流式解析,Any三種風格里自由混搭。雖然文檔不多,但還是有一些的?;故薔醯夢牡擋還?,請告訴我你的需求。

希望能引起大家的一點點興趣??饣購芐?,如果有 bug 歡迎提交 bug report 和 pull request 到 json-iterator/java。jsoniter 的 golang 版本會在稍后更新到和 java 版本一樣的水平,甚至更好。


作者:陶文
來源:知乎


上一篇: 四道Java基礎題 你能對幾道?

下一篇: JAVA要死了嗎?不!我來告訴你為什么!

分享到: 更多
中国足球竞彩网 重庆时时单双大小 北京pk10看走势方法 北京pk赛车四码计划 幸运飞艇免费网页计划 二人麻将免费下载 七乐彩中奖规则计划软件 德国赛车pk拾计划 重庆时时系统乱了吗 太子中心三肖中一肖 重庆老时时开奖结果 怎么猜大小规律 新江时时彩五星走势 球探足球比分直播数据 大乐透走势图带连线图 千炮捕鱼