V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
laoyur
V2EX  ›  C

RapidJSON 我真的不会用,求指点

  •  
  •   laoyur · 2015-05-05 14:29:07 +08:00 · 1617 次点击
    这是一个创建于 3498 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以前一直用的jsoncpp,各种好用。
    考虑到效率,现在想迁移到RapidJSON,可是发现真的不会用,官方文档也看了,还是有疑问。因为觉得是自己的使用问题,发到GitHub上感觉不太合适,所以就发到这里了。请各位轻喷。

    版本:试过master和1.0.1

    问题1:
    为什么以下的写法不对:

    Document doc;
    doc.SetObject();
    
    Value v(kArrayType);
    
    doc.AddMember("array1", v, doc.GetAllocator());
    

    必须使用这种方式才行:

    Document doc;
    doc.SetObject();
    
    Value v;
    doc.AddMember("array1", v, doc.GetAllocator());
    doc["array1"].SetArray();
    

    问题2:
    为什么以下代码段生成的json跟预想中的不一样

    Document doc;
    doc.SetObject();
    
    Value v;
    doc.AddMember("array1", v, doc.GetAllocator());
    doc["array1"].SetArray();
    
    for (int i = 0; i < 2; i++) {
    
        Value obj;
    
        doc["array1"].PushBack(obj, doc.GetAllocator());
        doc["array1"][i].SetObject();
    
        Value arrayOfObj;
    
        doc["array1"][i].AddMember("array2", arrayOfObj, doc.GetAllocator());
        doc["array1"][i]["array2"].SetArray();
    
        for (int j = 0; j < 2; j++) {
    
            Value obj1;
    
            doc["array1"][i]["array2"].PushBack(obj1, doc.GetAllocator());
            doc["array1"][i]["array2"][j].SetObject();
        }
    }
    
    StringBuffer buffer;
    PrettyWriter<StringBuffer> writer(buffer);
    doc.Accept(writer);
    
    const char* outputJson = buffer.GetString();
    

    最后生成的json是:

    {
        "array1":
        [
            {
                "array2":
                    [
                        {},
                        null
                    ]
            },
            null
        ]
    }
    

    预想中的应该是:

    {
        "array1":
        [
            {
                "array2":
                    [
                        {},
                        {}
                    ]
            },
            {
                "array2":
                    [
                        {},
                        {}
                    ]
            },
        ]
    }
    
    第 1 条附言  ·  2015-05-07 16:28:03 +08:00
    好吧,可以结帖了,结论是:我是傻逼。
    RapidJSON是一个headers-only-library,所以我在cocos2dx项目中混杂新旧两份源码是极其傻逼的做法。

    解决办法有以下几种:

    1. 老老实实用cocos2dx提供的旧版本,并坐等cocos2dx哪天心情好了更新;

    2. 自己把cocos2dx中的旧版本替换成新版本,不推荐。cocos2dx这货已经像打鸡血一样飙升到3.6版了,而且各种形式的版本让人眼花缭乱,还有什么cocos一站式服务的版本,改它源代码简直就是给自己找麻烦;

    3. 依然用jsoncpp,虽然效率稍低,但API用起来各种舒服;

    4. 偏执狂可以尝试用以下方式让RapidJSON的新旧版本共存:

    伪代码:

    #define RAPIDJSON_NAMESPACE myrapidjson //自定义新版rapidjson的命名空间,以跟旧版相互隔离
    #undef 所有RapidJSON源码中定义的宏,一大坨,每个.h文件一个,外加一个RAPIDJSON_PARSE_ERROR
    #include "rapidjson/..." //包含新版rapidjson头文件
    //开始写你的业务代码 blah blah
    //用myrapidjson命名空间使用新版rapidjson API...
    //新版rapidjson用完收工
    #undef RAPIDJSON_NAMESPACE //还原自定义的命名空间
    #undef 再次undef那一大坨宏,以至于不会污染到旧版
    10 条回复    2015-05-06 17:21:42 +08:00
    linux40
        1
    linux40  
       2015-05-06 07:30:46 +08:00 via Android
    知乎上有作者?
    laoyur
        2
    laoyur  
    OP
       2015-05-06 09:15:19 +08:00
    貌似作者也在v2,求火力支援,@ miloyip
    laoyur
        3
    laoyur  
    OP
       2015-05-06 09:16:17 +08:00
    上一条没@ 到,重发一下,@miloyip
    miloyip
        4
    miloyip  
       2015-05-06 10:13:32 +08:00
    第一个没问题:

    ~~~cpp
    TEST(Document, laoyur) {
    Document doc;
    doc.SetObject();

    Value v(kArrayType);

    doc.AddMember("array1", v, doc.GetAllocator());

    StringBuffer s;
    Writer<StringBuffer> writer(s);
    doc.Accept(writer);

    std::cout << s.GetString() << std::endl;
    }
    ~~~

    ~~~
    {"array1":[]}
    ~~~
    miloyip
        5
    miloyip  
       2015-05-06 10:17:11 +08:00
    刚测了,第二个也没问题啊……

    {"array1":[{"array2":[{},{}]},{"array2":[{},{}]}]}
    miloyip
        6
    miloyip  
       2015-05-06 10:19:20 +08:00
    你先看看是否有其他环境原因。之后我才解释,这种调用方法不太高效,怎么改进。
    laoyur
        7
    laoyur  
    OP
       2015-05-06 11:44:31 +08:00
    @miloyip 感谢作者亲临现场,👏

    之所以会有问题1,是因为如果把问题2中的代码全部换成问题1中的“错误”形式后,运行时直接崩了,挂在IsObject的断言处。
    考虑到问题2的奇怪表现,怀疑问题1也是因为问题2而牵连到了。

    考虑环境因素的话,我环境如下:
    XCode 6.2 Apple LLVM 6.0, iOS 8, cocos2dx 3.3,c++11,rapidjson版本master和1.0.1都试过
    cocos2dx其实自带rapidjson,不过版本较旧,我代码中使用了github版本的rapidjson
    laoyur
        8
    laoyur  
    OP
       2015-05-06 14:49:51 +08:00
    @miloyip 我重新建了个没有cocos2dx环境的工程,使用一模一样的compiler设置,问题2中的测试代码能正常运行,问题1也不复存在
    miloyip
        9
    miloyip  
       2015-05-06 16:30:31 +08:00
    我不介意你把问题写在issue里,集中在一个地方,可能对其他人也会有帮助。
    laoyur
        10
    laoyur  
    OP
       2015-05-06 17:21:42 +08:00
    @miloyip ok,我还会去cocoachina反映一下,看看有没有遇到相同情况的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3711 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 113ms · UTC 04:24 · PVG 12:24 · LAX 20:24 · JFK 23:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.