Json是數據交換經常使用的一種數據格式。C++標準庫並無包含任何Json標準的實現,因此咱們要藉助於一些第三方庫,jsoncpp就是一個經常使用的庫。因爲工做中常常用jsoncpp,發現這個庫問題很多,該篇文章本意是想深度吐槽一下這個函數庫,但在尋找證據的過程當中發現部分問題是由版本形成的,因此對問題進行一些說明,但願能幫助遇到一樣問題的朋友。ios
這也是我在工做中遇到的問題:在程序處理非法json串時,直接致使服務程序終止,即便使用try
塊包圍這段代碼,仍沒法成功捕獲異常。深刻閱讀它的實現代碼才發現,jsoncpp的異常處理是比較原始的,遇到異常直接assert
,因此程序直接就終止了。對於簡單的小程序來講,這無可厚非,但對於後端服務來講,這個問題很是嚴重,由於形成了服務不可用。json
通過再度挖掘,發現開發環境用的jsoncpp版本是0.5.0,因此異常處理機制原始;實際上在jsoncpp 0.8.3開始就對異常處理進行了改變,經過定義JSON_USE_EXCEPTION
宏改變了類型無效的行爲:小程序
If defined, indicates that Json use exception to report invalid type manipulation instead of C assert macro.
在最新版的1.8.4裏,JSON_USE_EXCEPTION=1
已是默認行爲了,除了註釋錯誤仍然調用assert
外,基本上其餘全部的錯誤都會拋出異常,再也不assert
了:後端
If non-zero, the library uses exceptions to report bad input instead of C assertion macros. The default is to use exceptions.
因此,最簡單的方案就是將庫升級爲最新版。若是由於一些緣由沒法升級函數庫,那最穩妥的方式就是在使用數據以前進行嚴格的數據檢查,除此以外沒有其餘更好的方式。數組
對於哪些錯誤可能致使異常,在jsoncpp.cpp
文件裏直接搜關鍵字JSON_ASSERT
、JSON_FAIL_MESSAGE
和assert
,找到對應異常所在的代碼,可讓你知道哪些具體狀況會致使異常,以及哪些是可捕捉的,哪些會引發程序終止的。app
說「蹩腳」,主要仍是由於它提供的API太老套,明顯沒跟上現代C++的步伐,同時跟C++的各種容器交互困難,大部分狀況須要人工寫代碼。好比:ide
現代C++加強了直觀的初始化,好比map的初始化函數
std::map<int,int> map {{1,1},{2,2}};
但jsoncpp並無提供這類json常量的初始化,咱們只能經過:ui
Json::Value root; Json::FastWriter writer; root["name"] = "ideami"; std::string json = writer.write(root); std::cout << json << std::endl;
人工構造,或者使用:idea
Json::Reader reader; Json::Value root; std::string jsonStr = "{\"name\":\"ideami\"}"; if (!reader.parse(jsonStr, root)) { return -1; }
缺少直觀性。
如std::vector<int>
類型的數組,若生成json數組,咱們只能:
#include <iostream> #include "json/json.h" #include <string> int main() { std::vector<int> v {1,2,3,4}; Json::Value array; Json::FastWriter writer; for (auto e : v) { array.append(e); } std::cout << writer.write(array) << std::endl; }
若是能提供直接轉換的功能就方便了...
總體上,jsoncpp提供的API比較難用,上面用的API都是老版的API,其提供的新版APIJson::CharReaderBuilder
、Json::StreamWriterBuilder
等易用性也不好。
在易用性上,JSON for Modern C++是一個更好的選擇。
請繼續關注個人公衆號文章