標籤:

jsoncpp和rapidjson哪個好用?


身為 RapidJSON 作者,剛剛做完 28 個 C/C++ JSON 庫(包括題目中的兩個)的評測 miloyip/nativejson-benchmark,回來回答這個問題。

標準符合程度(越高越好):

這個測試分開4個部分:JSON正確性檢測(使用JSON_checker測試集)、解析double的準確性、解析string的正確性、roundtrip測試。

JsonCpp 得88分,算是比較好的了。如果仔細看每個部分(https://rawgit.com/miloyip/nativejson-benchmark/master/sample/conformance.html),就是JSON正確性和roundtrip上有幾個問題。而RapidJSON在JSON正確性、string和roundtrip上都是滿分,開啟了 full precision 選項的話,解析double也是滿分。

解析和生成JSON的耗時(越低越好):

可見RapidJSON比JsonCpp在解析上快了一個數量級,而生成上也近一個數量級了。

解析至DOM後的內存用量(越低越好):

RapidJSON(除了insitu parsing)的內存用量只是JsonCpp的1/4。

其他方面,例如功能、文檔、友好性等,就不在此逐一對比了。

RapidJSON也有一些缺點,例如有些API的設計比較奇怪,可能較難使用。我們會嘗試加入一些功能,使不太注重性能的部分能更容易使用。

如果讀者仍然想使用 JsonCpp,也可以參考這個評測,幫助改進它。這也是我做此評測的初衷,在開源代碼中互相學習,持續改進。


沒人回答,我來回答一下吧,之前都用jsoncpp,自從發現rapidjson後,一直讓團隊用這個

易用性:rapidjson是全頭文件包含的,jsoncpp需要你內置編譯或編譯成庫;但rapidjson的一些介面不全,只提供了一層一層的這種解析方式,不能將某一層一次讀出來,實際用的時候,要簡單封裝一下,不然代碼量會很大;

性能:rapidjson的性能是現在所有的c++ json解析庫裡面最高的,沒有之一;

容錯性:rapidjson只支持標準的 json 格式,很多人以為這個是缺點,我覺得這個是優點,大家都按照標準做,這是成本最低的;

rapidjson之前是託管在Googe Code上的,現在已遷移到GitHub,地址:miloyip/rapidjson · GitHub

另外具體的性能測試,可以參考這個地址:mloskot/json_benchmark · GitHub

這是對流行C++ Json庫的一個總結:【總結】各種 JSON 解析庫的功能簡介

-----------------------------------

2015-03-30

Irons Du 推薦的nlohmann/json · GitHub,今天中午吃完飯,瞄了一下,發現這個庫比較符合我的審美,我喜歡一些小的東西,就做了一下簡易的測試

1,現在工作用的機器是Windows,本來想用VS2013隨便編譯下,最後發現不行,主要問題是:

1). 對內部類重定義為同名類,VS不支持這樣,其實我也覺得怪怪的,至少我不會這樣寫;

2). no_except關鍵字不認識

3). enable_if的邏輯處理,現在VS 2013不支持

前兩個倒好改,第三個就的確不想去改了,不過聽說VS2015-PRE能支持編譯

2,最後用MingGW(G++ 4.91)編譯了一下,使用-O2優化,跑了下測試如下:

nlohmannjson.small: 1000 iterations of 500 parsings in 4.6015 to 4.62655 sec based on 2 benchmarks

nlohmannjson.large: 1000 iterations of 1 parsings in 167.245 to 167.471 sec based on 2 benchmarks

順便在同一個機器上跑了一下rapidjson的測試

rapidjson.small: 1000 iterations of 500 parsings in 0.953772 to 0.954968 sec based on 2 benchmarks

rapidjson.large: 1000 iterations of 1 parsings in 14.1077 to 14.1594 sec based on 2 benchmarks

對照之前mloskot/json_benchmark · GitHub的測試數據,這個庫的性能還是不錯的,只是比起rapidjson還有不小差距

總結:

優點: 這個庫使用了大量的C++ 11標準元素,另外庫的設計上,也符合STL的一些標準,可配置性比較強;單文件方式,引用也比較方便;使用上,也有其獨到的地方,更接近JSON的本質;此外性能上還是不錯的,只是比rapidjson差,比libjson,jsoncpp之流還是強了不少

缺點: 不支持VS2013,並且看作者的意思,他也不會去兼容VS2013,但作為一個Win7統治桌面操作系統的時代,VS2013一定會是一個主流的編譯器,這一點說不過去;代碼上,Morden C++的大量使用,對於一般的程序員來說,太不友好了;性能,好吧,他的確比rapidjson慢了5~10倍。

結論:

玩票可以,實際項目還是用rapidjson吧


一開始被rapidjson的介紹感動了,用了之後發現有內存泄漏。在路上,等有空上代碼。


rapidjson介面設計的不好,不好用,雖然只需要包含頭文件,另外主要也是用了其他內建json類型的語言給慣壞了,jsoncpp要編譯成庫就更加不方便了。最近工作需要用json,github上找了下,這個nlohmann/json好,只需要一個hpp文件,介面設計的比較易用,整體評價也不錯,Linux下面gcc要4.9


如果只是問「好用」的話,我更傾向於選擇jsoncpp。介面設計的精巧簡練又易用,如果有需要,源碼也能半天內看完,實現讓人感覺很優美。而且是json官方推薦的解析工具。缺點就在於大量使用STL,相較而言解析效率一般般。

rapidjson時空效率確實表現出色,上面作者都親自站台了,我等渣渣也不好說什麼。只是怎麼說,介面和實現並不那麼接地氣,不客氣地說簡直是亂七八糟。因為我們之前穩定跑的是jsoncpp,所以考量之後還是放棄了

綜上,如果系統的瓶頸確定是在json解析上,那不妨試試rapidjson;如果只是為了避免這點性能損失,不建議rapidjson


不好使,整的都是些啥亂七八糟的介面啊,json轉string還亂碼了,棄之,煩人。


rapidjson太難用了,介面設計的很奇怪,不建議使用。


我測試了單線程和多線程下rapidjson和jsoncpp的效率

測試硬體環境:

Windows Server 2008 x64

intel E5-2620(2處理器,單顆cpu12核超線程)

16G內存

同樣條件下測試結果如下: | 平均每秒解析次數

線程數 | rapidjson | jsoncpp

1 | 329029 | 67993

2 | 381968 | 78100

4 | 203786 | 147608

8 | 152234 | 270810

12 | 124466 | 400020

16 | 51355 | 409102

24 | 52359 | 502005

rapidjson隨著線程數越大,單核利用率和總cpu利用率都呈下降趨勢,jsoncpp可以完全利用單核,並在24線程時總cpu利用率達到100%。

測試樣本如下:

{"NO":"京A12345","area1":"A","area2":0,"color":2,"data_type":4610,"gnsscenterid":50303,"gps":{"alarm":0,"altitude":114,"cmb_date":"2015-01-01 14:18:10","direction":194,"excrypt":0,"lat":"22.716590","lon":"138.608925","state":0,"time":"2015-06-11 14:18:07","vec1":26,"vec2":26,"vec3":34794},"type":0}

//以下是測試代碼中的主要部分,其中命名空間「rapidjson」中封裝了rapidjson的部分操作。
namespace rapidjson
{
static void parse(rapidjson::Document document, const char* msg)
{
if (document.Parse&<0&>(msg).HasParseError())
{
throw document.GetParseError();
}
}
static void parse(rapidjson::Document document, const std::string msg)
{
rapidjson::parse(document, msg.c_str());
}
}

void test_thread(int test_type)
{
if (test_type == TEST_RAPIDJSON)
{
while (is_running_)
{
rapidjson::Document root;
rapidjson::parse(root, content);

num_ ++;
}
}
else if (test_type == TEST_JSONCPP)
{
while (is_running_)
{
Json::Value root;
Json::Reader reader;
reader.parse(content, root);

num_ ++;
}
}
}
void start_test()
{
is_running_ = true;
for (int i=0; i&interrupt();
t-&>join();
}
thread_s_.clear();
}

void on_timer()
{
output(num_);
num_ = 0;
}


只用過jsoncpp.這貨用起來很簡單.

只是有個地方我不大明白,就是在本地序列化成json的時候,默認生成的是[{"key":"xxx"}]
這個樣子,而不是{"key":"xxx"}.注意後面還有個換行。而jsoncpp本身的格式檢測很嚴格,不是標準的json格式是解析不出來的, 所以外面加了個[ ]生成的json由jsoncpp的Reader類和Value類不能直接解析,還得做下字元串處理。

有點不能理解為什麼要這麼做,如果有知道為什麼的人請告訴我一下。

不過最近github上jsoncpp的更新蠻勤快的,不知道這個地方改了沒有,沒仔細看。

以後有機會試試rapidjson


我對RapidJSON的解析能力沒有任何疑問,雖然沒真正實測過,不過測試過RapidXML解析速度,比tiny之流快了一個數量級。其解析寫法也還湊合,沒什麼吐槽的

但還是要說以下一件事

開發一個跨平台的特效編輯器,用RapidJSON導出json文件(cocos集成這個庫,就直接拿來用),導出json文件死活有亂碼(/u000000),還有字元丟失的情況,也不知道是不是writer是不是有問題,折騰幾小時後,去git下來jsoncpp,集成項目很麻煩,棄之,然後果斷換成libjson,分分鐘問題解決了。


因為有一些特殊的需求, 於是自己寫了個json的解析

(只做了DOM,通過了JSON_checker的36個測試,

全部解析不超過300行, 用scanf處理的double)

在MAC系統

Processor: intel i5 3.2GHz,

Memory: 8GB 1867MHz DDR3

Compiler: Apple Clang 8.0 (編譯參數-O2)

上測試了twitter.json的解析,

在解析DOM和輸出文本這兩方面,都只佔用了rapidjson一半的時間。

nmsccjson use: 0.001614

nmsccjson use: 0.001219

nmsccjson use: 0.001189

nmsccjson use: 0.001189

nmsccjson use: 0.001183

rapidjson use: 0.004272

rapidjson use: 0.002522

rapidjson use: 0.002235

rapidjson use: 0.002527

rapidjson use: 0.002473

nmsccjson dump: 0.036483

rapidjson dump: 0.060545

以下是測試代碼

#include &
#include &
#include &
#include &

#include &
#include &
#include &

using namespace nms;

int main(int argc, char *argv[]) {

File twitter("twitter.json", File::Read);
const auto size = twitter.size();
auto str = new char[size+1];
twitter.read(str, size);
str[size] = "";

double nmsccjson_dump = 0;
double rapidjson_dump = 0;
// nmscc
{
Timer t;
JDoc json(str, size);
writef("twitter = {}
", json.value());
nmsccjson_dump = t.duration();

}

// rapidjson
{
Timer t;
rapidjson::Document doc;
doc.Parse(str);
rapidjson::OStreamWrapper osw(std::cout);
rapidjson::Writer& writer(osw);
doc.Accept(writer);
rapidjson_dump = t.duration();

}

printf("-------------------
");

// nmscc
for (int i = 0; i &< 5; ++i) { Timer t; JDoc json(str, size); printf("nmsccjson use: %f ", t.duration()); } // rapidjson for(int i = 0; i &< 5; ++i) { Timer t; rapidjson::Document doc; doc.Parse(str); printf("rapidjson use: %f ", t.duration()); } printf("nmsccjson dump: %f ", nmsccjson_dump); printf("rapidjson dump: %f ", rapidjson_dump); return 0; }


rapidjson在編譯開啟優化的時候,會有內存溢出的問題。(親測)


https://github.com/nlohmann/json


期待添加 https://developer.gnome.org/json-glib/ 和 http://doc.qt.io/qt-5/json.html benchmark 可能 GNOME、KDE沒有重json需求 :)


贊下rapidjson,性能不錯,介面不符合自己的習慣可以再次封裝下!


rap解析速度快很多


之前只是玩玩,並沒有深入到速度性能的層次,單從新手配置的角度來說,rapidjson我花了幾分鐘,jsoncpp用了幾天,還沒配好。。當然也有可能是我用了mfc的緣故。。。


jsoncpp is easy to use in ubuntu, generate a header file and just use, thats it.

not program in Windows many years...


贊同,都是裝逼貨。就一個簡單的字元串-&>json,整這麼多亂七八糟的介面,還綁定到事件了,吃飽了撐的?

c++er有這個需求的99%的也就是想將字元串格式轉換為便於操作的數組/鏈表而已。你就提供一個load/save和 添加刪除成員項的函數不就是了,搞那麼多亂七八糟的介面幹嘛,模板/分配器都來了,你是要上天么?

rxxxJSON 還建立了一個網站來宣傳。。。服了,有點噁心。還定義那麼多頭文件,莫名其妙的各種介面函數。

現在是互聯網時代,程序員找一個工具使用,目的是為了滿足業務需要的功能,而不是為了搞技術深度研究的。


推薦閱讀:

TAG:C | JSON | RapidJSON |