rapidjson使用总结

rapidjson简介

rapidjson是腾讯的开源json解析框架,用c++实现。由于全部代码仅用header file实现,所以很容易集成到项目中。

rapidjson的性能是很出色的,其作者Milo Yipz做了28个C/C++ JSON库的评测,这个链接里有测试的结果截图。

rapidjson的另一个特点是对json的标准符合程度是100%的(在开启了full precision选项的情况下)。

这里是官方教程:rapidjson官方教程

这里是原作者对rapidjson代码的剖析:rapidjson代码剖析

我之前的项目使用的是jsoncpp,最近在把解析json的代码交叉编译到iOS设备的时候,偶尔会出现crash的情况。虽然经过检查是代码写的有问题,不是jsoncpp的问题,在解决问题过程中尝试了rapidjson这个库,并顺便对比了一下jsoncpp和rapidjson对我项目中json文件的解析速度。

Dom解析示例

下面是我写的一个小例子,从test.json文件中读取内容并解析。其他代码示例也可以查看我的github仓库中关于rapidjson的测试代码:rapid_json_test.cpp.

 
// test.json
{
    "dictVersion": 1,  
    "content":  
    [   
        {"key": "word1", "value": "单词1"} ,
        {"key": "word2", "value": "单词2"} ,
        {"key": "word3", "value": "单词3"} ,
        {"key": "word4", "value": "单词4"} ,
        {"key": "word5", "value": "单词5"} 
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
1
2
3
4
5
6
7
8
9
10
11
12
 
// test.cpp
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include <fstream>
#include <string>
#include <cassert>
#include <iostream>
#define psln(x) std::cout << #x " = " << (x) << std::endl
void testSimpleDoc() {
    using std::string;
    using std::ifstream;
    // read json content into string.
    string      stringFromStream;
    ifstream    in;
    in.open("test.json", ifstream::in);
    if (!in.is_open())
        return;
    string line;
    while (getline(in, line)) {
        stringFromStream.append(line + "\n");
    }
    in.close();
    // ---------------------------- read json --------------------
    // parse json from string.
    using rapidjson::Document;
    Document doc;
    doc.Parse<0>(stringFromStream.c_str());
    if (doc.HasParseError()) {
        rapidjson::ParseErrorCode code = doc.GetParseError();
        psln(code);
        return;
    }
    // use values in parse result.
    using rapidjson::Value;
    Value & v = doc["dictVersion"];
    if (v.IsInt()) {
        psln(v.GetInt());
    }
    Value & contents = doc["content"];
    if (contents.IsArray()) {
        for (size_t i = 0; i < contents.Size(); ++i) {
            Value & v = contents[i];
            assert(v.IsObject());
            if (v.HasMember("key") && v["key"].IsString()) {
                psln(v["key"].GetString());
            }
            if (v.HasMember("value") && v["value"].IsString()) {
                psln(v["value"].GetString());
            }
        }
    }
    // ---------------------------- write json --------------------
    pcln("add a value into array");
    Value item(Type::kObjectType);
    item.AddMember("key", "word5", doc.GetAllocator());
    item.AddMember("value", "单词5", doc.GetAllocator());
    contents.PushBack(item, doc.GetAllocator());
    // convert dom to string.
    StringBuffer buffer;      // in rapidjson/stringbuffer.h
    Writer<StringBuffer> writer(buffer); // in rapidjson/writer.h
    doc.Accept(writer);
    psln(buffer.GetString());
}


Cocos2d-x 3.0 加入了rapidjson库用于json解析。位于项目的cocos2d/external/json下。

rapidjson 是一个不需要包含 .lib 和 .dll 即可运行的可见代码库。项目 wiki 见这里。下面通过两个实例来深入了解它在 cocos2dx 中的用法。

注:CCLOG() 函数需要在 DEBUG 模式下才有作用。

生成JSON文件并保存

[cpp] view plain copy
 
 
  1. #include "CCStdC.h"  
  2. #include "cocos2d.h"  
  3. #include "json/document.h"  
  4. #include "json/writer.h"  
  5. #include "json/stringbuffer.h"  
  6. using namespace  rapidjson;  
  7.   
  8. USING_NS_CC;  
  9.   
  10. int main()  
  11. {  
  12.     //*** 生成 json 文件,存储在 getWritablePath 文件夹下 ***  
  13.     rapidjson::Document writedoc;  
  14.     writedoc.SetObject();  
  15.     rapidjson::Document::AllocatorType& allocator = writedoc.GetAllocator();  
  16.     rapidjson::Value array(rapidjson::kArrayType);  
  17.     rapidjson::Value object(rapidjson::kObjectType);  
  18.       
  19.     // json object 格式添加 “名称/值” 对  
  20.     object.AddMember("inttag", 1, allocator);  
  21.     object.AddMember("doubletag", 1.0, allocator);  
  22.     object.AddMember("booltag"true, allocator);  
  23.     object.AddMember("hellotag""helloworld", allocator);  
  24.       
  25.     // json 加入数组  
  26.     array.PushBack(object, allocator);  
  27.       
  28.     // json object 格式添加 “名称/值” 对  
  29.     writedoc.AddMember("json""json string", allocator);  
  30.     writedoc.AddMember("array", array, allocator);  
  31.    
  32.     StringBuffer buffer;  
  33.     rapidjson::Writer<StringBuffer> writer(buffer);  
  34.     writedoc.Accept(writer);  
  35.   
  36.     auto path = FileUtils::getInstance()->getWritablePath();  
  37.     path.append("myhero.json");  
  38.     FILE* file = fopen(path.c_str(), "wb");  
  39.     if(file)  
  40.     {  
  41.         fputs(buffer.GetString(), file);  
  42.         fclose(file);  
  43.     }  
  44.     CCLOG("%s",buffer.GetString());  
  45.   
  46.     return 0;  
  47. }  


我是用 VS2012 编译的,最终生成的json文件位于 \proj.win32\Debug.win32 文件夹下。打开内容如下:

{"json":"json string","array":[{"inttag":1,"doubletag":1,"booltag":true,"hellotag":"helloworld"}]}

读取JSON文件并显示

rapidjson 需要根据原 json 格式单独编写解析方法,因此根据以上生成方法,解析方法应该为:

[cpp] view plain copy
 
 派生到我的代码片
  1. #include "CCStdC.h"  
  2. #include "cocos2d.h"  
  3. #include "json/document.h"  
  4. #include "json/writer.h"  
  5. #include "json/stringbuffer.h"  
  6. using namespace  rapidjson;  
  7.   
  8. USING_NS_CC;  
  9.   
  10. int main()  
  11. {  
  12.     auto path = FileUtils::getInstance()->getWritablePath();  
  13.     path.append("myhero.json");  
  14.   
  15.     //*** 读取 json 文件 ***  
  16.     rapidjson::Document readdoc;  
  17.     bool bRet = false;  
  18.     ssize_t size = 0;  
  19.     std::string load_str;  
  20.   
  21.     // getFileData 如果不指定,读取根目录是 Resource 文件夹  
  22.     unsigned char* titlech = FileUtils::getInstance()->getFileData(path, "r", &size);  
  23.     load_str = std::string((const char*)titlech,size);  
  24.   
  25.     //load_str = cocos2d::FileUtils::getInstance()->getStringFromFile("..\\myhero.json");  
  26.     readdoc.Parse<0>(load_str.c_str());     
  27.     if(readdoc.HasParseError())  
  28.     {  
  29.         CCLOG("GetParseError%s\n", readdoc.GetParseError());  
  30.     }  
  31.   
  32.     if(!readdoc.IsObject())  
  33.         return 0;  
  34.   
  35.     rapidjson::Value& _json = readdoc["json"];  
  36.     const char* ch = _json.GetString();  
  37.     cocos2d::log(ch);  
  38.     cocos2d::log(_json.GetString());  
  39.   
  40.     rapidjson::Value& _array = readdoc["array"];  
  41.     if(_array.IsArray())  
  42.     {  
  43.         CCLOG("test");  
  44.         for(int i=0; i<_array.Capacity(); i++)  
  45.         {  
  46.             //CCLOG("%d", i);  
  47.             rapidjson::Value& arraydoc = _array[i];  
  48.             if(arraydoc.HasMember("inttag"))  
  49.             {  
  50.                 int _inttag = arraydoc["inttag"].GetInt();  
  51.                 CCLOG("%d", _inttag);  
  52.             }  
  53.             if(arraydoc.HasMember("doubletag"))  
  54.             {  
  55.                 double _doubletag = arraydoc["doubletag"].GetDouble();  
  56.                 CCLOG("%lf", _doubletag);  
  57.             }  
  58.             if(arraydoc.HasMember("booltag"))  
  59.             {  
  60.                 bool _booltag = arraydoc["booltag"].GetBool();  
  61.                 CCLOG("%d", _booltag);  
  62.             }  
  63.             if(arraydoc.HasMember("hellotag"))  
  64.             {  
  65.                 const char* _hellotag = arraydoc["hellotag"].GetString();  
  66.                 CCLOG("%s", _hellotag);  
  67.             }  
  68.         }  
  69.     }  
  70.   
  71.     return 0;  
  72. }  
CCLOG 的最终显示为:

json string
json string
test
1
1.000000
1
helloworld

阅读更多

扫码向博主提问

Kaitiren

博客专家

非学,无以致疑;非问,无以广识
  • 擅长领域:
  • 区块链
  • Unity3D
  • Cocos2DX
去开通我的Chat快问
换一批

没有更多推荐了,返回首页