zoukankan      html  css  js  c++  java
  • rapidjson常见使用示例

    rapidjson相比jsoncpp性能高出太多,使用接口一样的简单的。官方中文帮助文档:http://rapidjson.org/zh-cn/。


    rapidjson的Move语意,请浏览http://rapidjson.org/zh-cn/md_doc_tutorial_8zh-cn.html#MoveSemantics,
    示例:
    rapidjson::Value a(123);
    rapidjson::Value b(456);
    b = a; // a变成Null,b变成数字123,这样的做法是基于性能考虑


    除了上述示例的复制语句外,AddMember()和PushBack()也采用了Move语意。


    深复制Value:
    Value v1("foo");
    // Value v2(v1); // 不容许
    Value v2(v1, a); // 制造一个克隆,v1不变


    Document d;
    v2.CopyFrom(d, a); // 把整个document复制至v2,d不变


    rapidjson为了最大化性能,大量使用了浅拷贝,使用之前一定要了解清楚。
    如果采用了浅拷贝,特别要注意局部对象的使用,以防止对象已被析构了,却还在被使用。


    // 需要#include的头文件:
    #include <rapidjson/document.h>
    #include <rapidjson/error/en.h> // en为english的简写,定义了取出错信息的函数GetParseError_En(errcode)
    #include <rapidjson/stringbuffer.h>
    #include <rapidjson/writer.h>


    // 示例1:解析一个字符串
    // 运行输出结果:
    // count=2
    // name=zhangsan
    // name=wangwu
    void x1()
    {
        rapidjson::Document document; // 定义一个Document对象
        std::string str = "{"count":2,"names":["zhangsan","wangwu"]}";


        document.Parse(str.c_str()); // 解析,Parse()无返回值,也不会抛异常
        if (document.HasParseError()) // 通过HasParseError()来判断解析是否成功
        {
            // 可通过GetParseError()取得出错代码,
            // 注意GetParseError()返回的是一个rapidjson::ParseErrorCode类型的枚举值
            // 使用函数rapidjson::GetParseError_En()得到错误码的字符串说明,这里的En为English简写
            // 函数GetErrorOffset()返回出错发生的位置
            printf("parse error: (%d:%d)%s ", document.GetParseError(), document.GetErrorOffset(), rapidjson::GetParseError_En(document.GetParseError()));
        }
        else
        {
            // 判断某成员是否存在
            if (!document.HasMember("count") || !document.HasMember("names"))
            {
                printf("invalid format: %s ", str.c_str());
            }
            else
            {
                // 如果count不存在,则运行程序会挂,DEBUG模式下直接abort
                rapidjson::Value& count_json = document["count"];
                
                // 如果count不是整数类型,调用也会挂,DEBUG模式下直接abort
                // GetInt()返回类型为int
                // GetUint()返回类型为unsigned int
                // GetInt64()返回类型为int64_t
                // GetUint64()返回类型为uint64_t
                // GetDouble()返回类型为double
                // GetString()返回类型为char*
                // GetBool()返回类型为bool
                int count = count_json.GetInt();
                printf("count=%d ", count);
                
                // 方法GetType()返回枚举值: kNullType,kFalseType,kTrueType,kObjectType,kArrayType,kStringType,kNumberType
                // 可用IsArray()判断是否为数组,示例: { "a": [1, 2, 3, 4] }
                // 用IsString()判断是否为字符串值
                // 用IsDouble()判断是否为double类型的值,示例: { "pi": 3.1416 }
                // 用IsInt()判断是否为int类型的值
                // 用IsUint()判断是否为unsigned int类型的值
                // 用IsInt64()判断是否为int64_t类型的值
                // 用IsUint64()判断是否为uint64_t类型的值
                // 用IsBool()判断是否为bool类型的值
                // 用IsFalse()判断值是否为false,示例: { "t": true, "f": false }
                // 用IsTrue()判断值是否为true
                // 用IsNull()判断值是否为NULL,示例: { "n": null }
                // 更多说明可浏览:
                // https://miloyip.gitbooks.io/rapidjson/content/zh-cn/doc/tutorial.zh-cn.html


                const rapidjson::Value& names_json = document["names"];
                for (rapidjson::SizeType i=0; i<names_json.Size(); ++i)
                {
                    std::string name = names_json[i].GetString();
                    printf("name=%s ", name.c_str());
                }
            }
        }
    }


    // 示例2:构造一个json并转成字符串
    // 输出结果:
    // {"count":2,"names":[{"name":"zhangsan"},{"name":"wangwu"}]}
    void x2()
    {
        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);


        writer.StartObject();


        // count
        writer.Key("count");
        writer.Int(2);
        // 写4字节有符号整数: Int(int32_t x)
        // 写4字节无符号整数: Uint(uint32_t x)
        // 写8字节有符号整数: Int64(int64_t x)
        // 写8字节无符号整数: Uint64(uint64_t x)
        // 写double值: Double(double x)
        // 写bool值: Bool(bool x)


        // names
        writer.Key("names");
        writer.StartArray();


        writer.StartObject();
        writer.Key("name");
        writer.String("zhangsan");
        writer.EndObject();


        writer.StartObject();
        writer.Key("name");
        writer.String("wangwu");
        writer.EndObject();


        writer.EndArray();
        writer.EndObject();


        // 以字符串形式打印输出
        printf("%s ", buffer.GetString());
    }


    // 示例3:修改一个已有的json字符串
    // 运行输出结果:
    // {"name":"wangwu","age":22}
    void x3()
    {
        rapidjson::Document document;
        std::string str = "{"name":"zhangsan","age":20}";
        document.Parse(str.c_str());


        rapidjson::Value& name_json = document["name"];
        rapidjson::Value& age_json = document["age"];
        std::string new_name = "wangwu";
        int new_age = 22;


        // 注意第三个参数是document.GetAllocator(),相当于深拷贝,rapidjson会分配一块内存,然后复制new_name.c_str(),
        // 如果不指定第三个参数,则是浅拷贝,也就是rapidjson不会分配一块内存,而是直接指向new_name.c_str(),省去复制提升了性能
        // 官方说明:
        // http://rapidjson.org/zh-cn/md_doc_tutorial_8zh-cn.html#CreateString
        name_json.SetString(new_name.c_str(), new_name.size(), document.GetAllocator());
        age_json.SetInt(new_age);


        // 转成字符串输出
        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        document.Accept(writer);
        printf("%s ", buffer.GetString());
    }


    // 示例4:读数组
    // 运行输出结果:
    // zhangsan wangwu 
    void x4()
    {
        rapidjson::Document document;
        std::string str = "{"count":2,"names":[{"name":"zhangsan"},{"name":"wangwu"}]}";


        document.Parse(str.c_str());
        if (document.HasParseError())
        {
            printf("parse error: %d ", document.GetParseError());
        }
        else
        {
            rapidjson::Value& names_json = document["names"];
            for (rapidjson::SizeType i=0; i<names_json.Size(); ++i)
            {
                if (names_json[i].HasMember("name"))
                {
                    rapidjson::Value& name_json = names_json[i]["name"];
                    printf("%s ", name_json.GetString());
                }
            }
            printf(" ");
        }
    }


    // 示例5: 以Writer构造一个json,然后修改它,最后转成字符串
    // 运行输出结果:
    // {"count":2}
    // {"count":8}
    void x5()
    {
        rapidjson::StringBuffer buffer1;
        rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
        
        writer1.StartObject();
        writer1.Key("count");
        writer1.Int(2);    
        writer1.EndObject();
        printf("%s ", buffer1.GetString());


        // 转成Document对象
        rapidjson::Document document;
        document.Parse(buffer1.GetString());


        // 修改
        rapidjson::Value& count_json = document["count"];
        count_json.SetInt(8);
        
        // 转成字符串
        rapidjson::StringBuffer buffer2;
        rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);


        document.Accept(writer2);
        printf("%s ", buffer2.GetString());
    }


    // 示例6: 以Document构造一个json,然后修改它,最后转成字符串
    // 运行输出结果:
    // {"count":3,"names":[{"id":1,"name":"zhangsan"}]}
    // {"count":9,"names":[{"id":1,"name":"zhangsan"}]}
    void x6()
    {
        rapidjson::Document document;
        std::string str = "{}"; // 这个是必须的,且不能为"",否则Parse出错
        document.Parse(str.c_str());


        // 新增成员count
        document.AddMember("count", 3, document.GetAllocator());


        // 新增数组成员
        rapidjson::Value array(rapidjson::kArrayType);
        rapidjson::Value object(rapidjson::kObjectType); // 数组成员
        object.AddMember("id", 1, document.GetAllocator()); 
        object.AddMember("name", "zhangsan", document.GetAllocator()); 
        
        // 如果数组添加无名字的成员,定义Value时应当改成相应的类型,如:
        //rapidjson::Value value(rapidjson::kStringType);
        //rapidjson::Value value(rapidjson::kNumberType);
        //rapidjson::Value value(rapidjson::kFalseType);
        //rapidjson::Value value(rapidjson::kTrueType);
        //array.PushBack(value, document.GetAllocator());
        //效果将是这样:'array':[1,2,3,4,5]
        
        // 注意下面用法编译不过:
        //std::string str1 = "hello";
        //object.AddMember("name", str1.c_str(), document.GetAllocator());
        //const char* str2 = "hello";
        //object.AddMember("name", str2, document.GetAllocator());
        //
        // 下面这样可以:
        //object.AddMember("name", "hello", document.GetAllocator());
        //const char str3[] = "hello";
        //object.AddMember("name", str3, document.GetAllocator());
        //    
        //std::string str4 = "#####";
        //rapidjson::Value v(str4.c_str(), document.GetAllocator());
        //obj.AddMember("x", v, document.GetAllocator());
        // 上面两行也可以写在一行:
        //obj.AddMember("x", rapidjson::Value(str4.c_str(), document.GetAllocator()).Move(), document.GetAllocator());


        // 添加到数组中
        array.PushBack(object, document.GetAllocator());
        // 添加到document中
        document.AddMember("names", array, document.GetAllocator());


        // 转成字符串输出
        rapidjson::StringBuffer buffer1;
        rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
        document.Accept(writer1);
        printf("%s ", buffer1.GetString());
        
        // 修改值
        rapidjson::Value& count_json = document["count"];
        count_json.SetInt(9);


        // 再次输出
        rapidjson::StringBuffer buffer2;
        rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);
        document.Accept(writer2);
        printf("%s ", buffer2.GetString());
    }


    // 不转义就输出
    // 示例7: 以Document构造一个json,然后修改它,最后转成字符串
    // 运行输出结果:
    // x7=>
    // {"title":"u8D2Bu56F0u5B64u513Fu52A9u517B"}
    void x7()
    {
        std::string root = "{}";
        rapidjson::Document document;
        document.Parse(root.c_str());


        std::string title = "u8D2Bu56F0u5B64u513Fu52A9u517B";
        document.AddMember("title", rapidjson::Value(title.c_str(), document.GetAllocator()).Move(), document.GetAllocator());


        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<> > writer(buffer);
        // 如果上面一句改成普通的:
        // rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        // 则输出将变成:
        // x7=>
        // 贫困孤儿助养
        
        document.Accept(writer);
        printf("x7=> %s ", buffer.GetString());
    }


    // 示例8:构造空对象和数组 
    // 运行输出结果:
    // {"age":{},"times":{},"names":[],"urls":[],"books":[]}
    // {"age":6,"times":{},"names":[],"urls":[],"books":[]}
    void x8()
    {
        rapidjson::Document document;
        document.Parse("{}"); // 这里换成document.SetObject()也可以


        // 下面为2种构造空对象的方法
        document.AddMember("age", rapidjson::Value(rapidjson::kObjectType).Move(), document.GetAllocator());
        document.AddMember("times", rapidjson::Value().SetObject(), document.GetAllocator());


        // 下面为2种构造空数组的方法
        document.AddMember("names", rapidjson::Value(rapidjson::kArrayType).Move(), document.GetAllocator());
        document.AddMember("urls", rapidjson::Value(rapidjson::kArrayType).Move(), document.GetAllocator());
        document.AddMember("books", rapidjson::Value().SetArray(), document.GetAllocator());


        rapidjson::StringBuffer buffer1;
        rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
        document.Accept(writer1);
        printf("%s ", buffer1.GetString());


        rapidjson::Value& age = document["age"];
        age.SetInt(6);


        rapidjson::StringBuffer buffer2;
        rapidjson::Writer<rapidjson::StringBuffer> writer2(buffer2);
        document.Accept(writer2);
        printf("%s ", buffer2.GetString());
    }


    // 删除数组元素
    // 示例运行输出:
    // { "names": [ {"name":"zhangsan","age":100}, {"name":"wangwu","age":90}, {"name":"xiaozhang","age":20} ]}
    // {"names":[{"name":"zhangsan","age":100},{"name":"wangwu","age":90}]}
    void x9()
    {
        std::string str = "{ "names": [ {"name":"zhangsan","age":100}, {"name":"wangwu","age":90}, {"name":"xiaozhang","age":20} ]}";
        
        rapidjson::Document document;
        document.Parse(str.c_str());
        
        rapidjson::Value& names_json = document["names"];
        for (rapidjson::Value::ValueIterator iter=names_json.Begin(); iter!=names_json.End();)
        {
            std::string name = (*iter)["name"].GetString();
            
            // 不要小张了
            if (name == "xiaozhang")
                iter = names_json.Erase(iter);
            else
                ++iter;
        }
        
        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        document.Accept(writer);
        
        printf("%s ", str.c_str());
        printf("%s ", buffer.GetString());
    }


    int main()
    {
        x1();
        x2();
        x3();
        x4();
        x5();
        x6();
        x7();
        x8();
        x9();
        return 0;
    }


    // 示例:不转义中文
    // 运行输出结果:
    //{"title":"贫困孤儿助养"}
    //{"title":"u8D2Bu56F0u5B64u513Fu52A9u517B"}
    //g++ -g -o b b.cpp -I/usr/local/thirdparty/rapidjson/include
    #include <rapidjson/document.h>
    #include <rapidjson/stringbuffer.h>
    #include <rapidjson/writer.h>
    #include <string>
    #include <stdio.h>


    int main()
    {
        std::string str = "{"title":"u8d2bu56f0u5b64u513fu52a9u517b"}";
        rapidjson::Document document;
        document.Parse(str.c_str());
        if (document.HasParseError())
        {
            printf("parse %s failed ", str.c_str());
            exit(1);
        }


        rapidjson::StringBuffer buffer1;
        rapidjson::Writer<rapidjson::StringBuffer> writer1(buffer1);
        document.Accept(writer1);
        printf("%s ", buffer1.GetString());


        rapidjson::StringBuffer buffer2;
        rapidjson::Writer<rapidjson::StringBuffer, rapidjson::Document::EncodingType, rapidjson::ASCII<> > writer2(buffer2);
        document.Accept(writer2);
        printf("%s ", buffer2.GetString());


        return 0;
    }


    // 辅助函数:任意类型都以字符串返回,
    // 如果不存在,或者为数组则返回空字符串。
    std::string rapidjson_string_value(rapidjson::Value& value, const std::string& name)
    {
        if (!value.HasMember(name.c_str()))
            return std::string("");


        const rapidjson::Value& child = value[name.c_str()];
        if (child.IsString())
            return child.GetString();


        char str[100];
        if (child.IsInt())
        {
            snprintf(str, sizeof(str), "%d", child.GetInt());
        }
        else if (child.IsInt64())
        {
            // 为使用PRId64,需要#include <inttypes.h>,
            // 同时编译时需要定义宏__STDC_FORMAT_MACROS
            snprintf(str, sizeof(str), "%"PRId64, child.GetInt64());
        }
        else if (child.IsUint())
        {
            snprintf(str, sizeof(str), "%u", child.GetUint());
        }
        else if (child.IsUint64())
        {
            snprintf(str, sizeof(str), "%"PRIu64, child.GetUint64());
        }
        else if (child.IsDouble())
        {
            snprintf(str, sizeof(str), "%.2lf", child.GetDouble());
        }
        else if (child.IsBool())
        {
            if (child.IsTrue())
                strcpy(str, "true");
            else
                strcpy(str, "false");
        }
        else
        {
            str[0] = '';
        }


        return str;
    }


    // 辅助函数:
    // 当为int32_t值,或字符串实际为int32_t值时,返回对应的int32_t值,其它情况返回0
    int32_t rapidjson_int32_value(rapidjson::Value& value, const std::string& name)
    {
        if (!value.HasMember(name.c_str()))
            return 0;


        const rapidjson::Value& child = value[name.c_str()];
        if (child.IsInt())
        {
            return child.GetInt();
        }
        else if (child.IsString())
        {
            return atoi(child.GetString());
        }


        return 0;
    }


    // 辅助函数:
    // 当为int64_t值,或字符串实际为int64_t值时,返回对应的int64_t值,其它情况返回0
    int64_t rapidjson_int64_value(rapidjson::Value& value, const std::string& name)
    {
        if (!value.HasMember(name.c_str()))
            return 0;


        const rapidjson::Value& child = value[name.c_str()];
        if (child.IsInt64())
        {
            return child.GetInt64();
        }
        else if (child.IsString())
        {
            return (int64_t)atoll(child.GetString());
        }


        return 0;
    }


    // 辅助函数:
    // 当为uin32_t值,或字符串实际为uin32_t值时,返回对应的uin32_t值,其它情况返回0
    uint32_t rapidjson_uint32_value(rapidjson::Value& value, const std::string& name)
    {
        if (!value.HasMember(name.c_str()))
            return 0;


        const rapidjson::Value& child = value[name.c_str()];
        if (child.IsUint())
        {
            return child.GetUint();
        }
        else if (child.IsString())
        {
            return (uint32_t)atoll(child.GetString());
        }


        return 0;
    }


    // 辅助函数:
    // 当为uin64_t值,或字符串实际为uin64_t值时,返回对应的uin64_t值,其它情况返回0
    uint64_t rapidjson_uint64_value(rapidjson::Value& value, const std::string& name)
    {
        if (!value.HasMember(name.c_str()))
            return 0;


        const rapidjson::Value& child = value[name.c_str()];
        if (child.IsUint64())
        {
            return child.GetUint64();
        }
        else if (child.IsString())
        {
            return (uint64_t)atoll(child.GetString());
        }


        return 0;
    }


    // schema使用示例:
    json的schema用来检验json数据,它也采用了json格式。


    rapidjson::Document schema_document;
    schema_document.Parse(schema.c_str());


    if (!schema_document.HasParseError())
    {
        rapidjson::Document document;
        document.Parse(str.c_str());
        
        if (!document.HasParseError())
        {
            SchemaDocument schema(schema_document);
            SchemaValidator validator(schema);
            if (!document.Accept(validator))
            {
                 // 检验出错,输出错误信息
                 StringBuffer sb;
                 validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
                 
                 printf("Invalid schema: %s ", sb.GetString());
                 printf("Invalid keyword: %s ", validator.GetInvalidSchemaKeyword());
                 
                 sb.Clear();
                 validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
                 printf("Invalid document: %s ", sb.GetString());
            }
        }
    }


    示例json:
    {
        "id": 1,
        "name": "A green door",
        "price": 12.50,
        "tags": ["home", "green"]
    }


    上段json对应的schema:
    {
        "$schema": "http://json-schema.org/draft-04/schema#",
        "title": "Product",
        "description": "A product from Acme's catalog",
        "type": "object",
        
        "properties": {
            "id": {
                "description": "The unique identifier for a product",
                "type": "integer"
            },
            "name": {
                "description": "Name of the product",
                "type": "string"
            },
            "price": {
                "type": "number",
                "minimum": 0,
                "exclusiveMinimum": true
            },
            "tags": {
                "type": "array",
                "items": {
                    "type": "string"
                },
                "minItems": 1,
                "uniqueItems": true
            }
        },
        "required": ["id", "name", "price"]
    }


    "title"和"description"是描述性的,可以不写。$schema也是可选的,依据的是《JSON Schema Draft v4》。


    X1)rapidjson的“坑”
    使用不当,则会掉进“坑”里。下列代码在valgrind中运行时,会报大量错误,而且如果sub是在一个循环中被AddMember,则无法得到预期的结果。
    从现象看像是sub析构后仍在被使用,为验证这个推测,改成:rapidjson::Document* sub = new rapidjson::Document;,然后再使用不但valgrind不报错,而且循环使用也没问题,那么可以肯定AddMember是浅拷贝,这样一来使用就不方便了,除非还有深拷贝的调用方式。


    #include <rapidjson/schema.h>
    #include <rapidjson/document.h>
    #include <rapidjson/stringbuffer.h>
    #include <rapidjson/writer.h>
    #include <string>
    #include <vector>


    int main()
    {
        rapidjson::Document doc;
        doc.Parse("{}");


        { // 目的是让sub在printf时已无效
            rapidjson::Document sub;
            sub.Parse("{"name":"tom"}");
            doc.AddMember("sub", sub, doc.GetAllocator());
        }


        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        doc.Accept(writer);
        printf("%s ", buffer.GetString());
        return 0;
    }


    上述代码在valgrind中跑,会报错大量如下这样的错误:
    ==30425== Invalid read of size 2
    ==30425==    at 0x804B008: rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::IsString() const (document.h:947)
    ==30425==    by 0x8051632: bool rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> >::Accept<rapidjson::Writer<rapidjson::GenericStringBuffer<rapidjson::UTF8<char>, rapidjson::CrtAllocator>, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0u> >(rapidjson::Writer<rapidjson::GenericStringBuffer<rapidjson::UTF8<char>, rapidjson::CrtAllocator>, rapidjson::UTF8<char>, rapidjson::UTF8<char>, rapidjson::CrtAllocator, 0u>&) const (document.h:1769)
    ==30425==    by 0x80488CE: main (f.cpp:30)
    ==30425==  Address 0x428eb62 is 58 bytes inside a block of size 65,548 free'd
    ==30425==    at 0x4023329: free (vg_replace_malloc.c:473)
    ==30425==    by 0x804BC72: rapidjson::CrtAllocator::Free(void*) (allocators.h:79)
    ==30425==    by 0x804BDD7: rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>::Clear() (allocators.h:148)
    ==30425==    by 0x804BE2E: rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>::~MemoryPoolAllocator() (allocators.h:140)
    ==30425==    by 0x804BE5F: rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::Destroy() (document.h:2382)
    ==30425==    by 0x804BE7E: rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator>::~GenericDocument() (document.h:2064)


    正确可以使用的写法:
    #include <rapidjson/schema.h>
    #include <rapidjson/document.h>
    #include <rapidjson/stringbuffer.h>
    #include <rapidjson/writer.h>
    #include <string>
    #include <vector>


    int main()
    {
        std::vector<rapidjson::Document*> subs;
        rapidjson::Document doc;
        doc.Parse("{}");


        {    
            // 注意,下面没有使用Document的默认构造,
            // 而是指定Allocator为其父的Allocator。
            // 如果存在多级Document,一定要统一使用根Document的Allocator,
            // 原因是Allocator分配的内存会随Document析构被释放掉!
            //
            // 如果不这样做,必须保证sub的生命在doc之后才结束。
            rapidjson::Document sub(&doc.GetAllocator());
            sub.Parse("{"name":"tom"}");
            doc.AddMember("sub", sub, doc.GetAllocator());
        }


        rapidjson::StringBuffer buffer;
        rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
        doc.Accept(writer);
        printf("%s ", buffer.GetString());


        for (std::vector<rapidjson::Document*>::size_type i=0; i<subs.size(); ++i)
        {
            rapidjson::Document *sub_ptr = subs[i];
            delete sub_ptr;
        }
        subs.clear();


        return 0;
    }


    x2)rapidjson的schema特性使用示例
    #include <rapidjson/document.h>
    #include <rapidjson/schema.h>
    #include <rapidjson/stringbuffer.h>


    int main()
    {
        std::string str = "{"aaa":111,"aaa":222}"; // "{"aaa":111,"a":222}"
    #if 0
        std::string schema_str = "{"type":"object","properties":{"aaa":{"type":"integer"},"bbb":{"type":"string"}},"required":["aaa","bbb"]}";
    #else
        std::string schema_str = "{"type":"object","properties":{"aaa":{"type":"integer"},"bbb":{"type":"integer"}},"required":["aaa","bbb"]}";
    #endif
        printf("%s ", str.c_str());
        printf("%s ", schema_str.c_str());


        rapidjson::Document doc;
        rapidjson::Document schema_doc;


        schema_doc.Parse(schema_str.c_str());
        doc.Parse(str.c_str());


        rapidjson::SchemaDocument schema(schema_doc);
        rapidjson::SchemaValidator validator(schema);
        if (doc.Accept(validator))
        {
            printf("data ok ");
        }
        else
        {
            rapidjson::StringBuffer sb;
            validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);


            printf("Invalid schema: %s ", sb.GetString());
            printf("Invalid keyword: %s ", validator.GetInvalidSchemaKeyword());


            sb.Clear();
            validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
            printf("Invalid document: %s ", sb.GetString());
        }


        return 0;
    }


    *) 特别注意rapidjson::Document可以为object, array, number, string, boolean, null中任意一种类型
       只有为object时才可以调用HasMember等与object有关的方法
    #include <rapidjson/document.h>
    #include <rapidjson/error/en.h>
    #include <rapidjson/stringbuffer.h>
    #include <rapidjson/writer.h>
    #include <stdio.h>


    int main(int argc, char* argv[])
    {
        std::string str;
        rapidjson::Document doc;
        doc.Parse(argv[1]);
        if (doc.HasParseError())
            printf("parse error ");
            
        // 注意doc可为object, array, number, string, boolean, null中任意一种类型
        if (!doc.IsObject())
            printf("not object ");
        else
        {
            printf("parse ok ");
            if (doc.IsNumber())
            printf("%d ", doc.GetInt());
            
            // doc为object类型时,才能调用HasMember
            if (doc.HasMember("x"))
                printf("has x ");
            else
                printf("without x ");
        }


        return 0;
    }


    遍历成员:
    rapidjson::Value value;
    。。。
    for (rapidjson::Value::ConstMemberIterator iter = value.MemberBegin(); iter!=value.MemberEnd(); ++iter)
    {
        const rapidjson::Value& name_json = iter->name; // 这个必须是字符串
        const rapidjson::Value& value_json = iter->value; // 这个可以为对象、数组等
        printf("%s ", name_json.GetString());
    }

  • 相关阅读:
    assert出问题了?
    UIWebView 禁止检测链接弹出UIActionSheet
    UIWebView 禁止检测链接弹出UIActionSheet
    Linux命令行下常用svn命令
    Linux命令行下常用svn命令
    续上文,Unity3D面试ABC
    续上文,Unity3D面试ABC
    部署 H3C CAS E0306
    部署 H3C CAS E0306
    H3C CAS 介绍 & 基本概念
  • 原文地址:https://www.cnblogs.com/aquester/p/9891573.html
Copyright © 2011-2022 走看看