RapidJSON优点

  • 跨平台
    编译器:Visual Studio、gcc、clang 等
    架构:x86、x64、ARM 等
    操作系统:Windows、Mac OS X、Linux、iOS、Android 等

  • 容易安装
    只有头文件的库。只需把头文件复制至你的项目中。

  • 独立、最小依赖
    不需依赖 STL、BOOST 等。
    只包含 <cstdio>, <cstdlib>, <cstring>, <inttypes.h>, <new>, <stdint.h>。

  • 没使用 C++ 异常、RTTI

  • 高性能
    使用模版及内联函数去降低函数调用开销。
    内部经优化的 Grisu2 及浮点数解析实现。
    可选的 SSE2/SSE4.2 支持。

RapidJSON教程

1、Value 及 Document

每个 JSON 值都储存为 Value 类,一个 Value 类可包含不同类型的值,而 Document 类则表示整个 DOM,它存储了一个 DOM 树的根 Value。
定义一个JSON字符串,把它解析至一个 Document:

#include "rapidjson/document.h"using namespace rapidjson;// ...const char* json =
{"hello": "world","t": true ,"f": false,"n": null,"i": 123,"pi": 3.1416,"a": [1, 2, 3, 4]
}Document document;
document.Parse(json);
//JSON.parse()
//在接收服务器数据时一般是字符串。
//可以使用 JSON.parse() 将数据转换为 JavaScript 对象。

那么现在该 JSON 就会被解析至 document 中,成为一棵DOM 树:

2、查询Value

//根是一个 Object,验证它的类型
assert(document.IsObject());//查询一下根 Object 中有没有 "hello" 成员
//在此例中,"hello" 成员关联到一个 JSON String
assert(document.HasMember("hello"));
assert(document["hello"].IsString());
printf("hello = %s\n", document["hello"].GetString());
//打印结果:world//JSON True/False 值是以 bool 表示的。
assert(document["t"].IsBool());
printf("t = %s\n", document["t"].GetBool() ? "true" : "false");
//打印结果:true//JSON Null 值可用 IsNull() 查询。
printf("n = %s\n", document["n"].IsNull() ? "null" : "?");
//打印结果:null//JSON Number 类型表示所有数值
//然而,C++ 需要使用更专门的类型
assert(document["i"].IsNumber());
assert(document["i"].IsInt());// 在此情况下,IsUint()/IsInt64()/IsUint64() 也会返回 true
printf("i = %d\n", document["i"].GetInt());
//打印结果:i = 123
assert(document["pi"].IsNumber());
assert(document["pi"].IsDouble());
printf("pi = %g\n", document["pi"].GetDouble());
//打印结果:pi = 3.1416// 使用引用来连续访问,方便之余还更高效。
const Value& a = document["a"];
assert(a.IsArray());
for (SizeType i = 0; i < a.Size(); i++) // 使用 SizeType 而不是 size_tprintf("a[%d] = %d\n", i, a[i].GetInt());
//打印结果:a[0] = 1
//         a[1] = 2
//         a[2] = 3
//         a[3] = 4//用迭代器去访问所有 Object 成员:
static const char* kTypeNames[] =
{"Null", "False", "True", "Object", "Array", "String", "Number"
};//若我们不确定一个成员是否存在,便需要在调用
//1、HasMember()
//2、operator[](const char*)
//然而,这会导致两次查找
//更好的做法是调用 FindMember()
//它能同时检查成员是否存在并返回它的 Value
Value::ConstMemberIterator itr = document.FindMember("hello");
if (itr != document.MemberEnd())printf("%s\n", itr->value.GetString());
//打印结果:worldfor (Value::ConstMemberIterator itr = document.MemberBegin();itr != document.MemberEnd(); ++itr)
{printf("Type of member %s is %s\n",itr->name.GetString(), kTypeNames[itr->value.GetType()]);
}
//打印结果:Type of member hello is String
//         Type of member t is True
//         Type of member f is False
//         Type of member n is Null
//         Type of member i is Number
//         Type of member pi is Number
//         Type of member a is Array//当使用 C++11 功能时,你可使用范围 for 循环去访问 Object 内的所有成员。
for (auto& m : document.GetObject())printf("Type of member %s is %s\n",m.name.GetString(), kTypeNames[m.value.GetType()]);
//打印结果:Type of member hello is String
//         Type of member t is True
//         Type of member f is False
//         Type of member n is Null
//         Type of member i is Number
//         Type of member pi is Number
//         Type of member a is Array//比较两个 Value
//使用 == 及 != 去比较两个 Value
//当且仅当 两个 Value 的类型及内容相同,它们才当作相等
if (document["hello"] == document["n"]) /*...*/;    // 比较两个值
if (document["hello"] == "world") /*...*/;          // 与字符串字面量作比较
if (document["i"] != 123) /*...*/;                  // 与整数作比较
if (document["pi"] != 3.14) /*...*/;                // 与 double 作比较

JSON 只提供一种数值类型──Number。数字可以是整数或实数,而 C++ 提供多种整数及浮点数类型 当查询一个 Number 时,你可以检查该数字是否能以目标类型来提取:

查检 提取
bool IsNumber() 不适用
bool IsUint() unsigned GetUint()
bool IsInt() int GetInt()
bool IsUint64() uint64_t GetUint64()
bool IsInt64() int64_t GetInt64()
bool IsDouble() double GetDouble()

3、创建/修改Value

当使用默认构造函数创建一个 Value 或 Document,它的类型便会是 Null。要改变其类型,需调用 SetXXX() 或赋值操作,例如:

Document d; // Null
d.SetObject();Value v;    // Null
v.SetInt(10);//重载构造函数:
Value b(true);              // 调用 Value(bool)
Value i(-123);              // 调用 Value(int)
Value u(123u);              // 调用 Value(unsigned)
Value d(1.5);               // 调用 Value(double)
//Value(Type)
Value o(kObjectType);       // 调用 Value(空object)
Value a(kArrayType);        // 调用 Value(空array)

转移语义(Move Semantics)
在设计 RapidJSON 时,Value 赋值并不是把来源 Value 复制至目的 Value,而是把来源 Value 转移(move)至目的 Value,AddMember(), PushBack() 也采用转移语义。例如:

Value a(123);
Value b(456);
b = a;
// a 变成 Null,b 变成数字 123。
// 优点:提高性能Value o(kObjectType);
{Value contacts(kArrayType);// 把元素加进 contacts 数组。// ...o.AddMember("contacts", contacts, d.GetAllocator());// contacts 在这里变成 Null。它的析构是平凡的。
}

转移语义——临时值
有时候,想直接构造一个 Value 并传递给一个“转移”函数(如 PushBack()、AddMember())。由于临时对象是不能转换为正常的 Value 引用,加入了一个方便的 Move() 函数:

Value a(kArrayType);
Document::AllocatorType& allocator = document.GetAllocator();
// a.PushBack(Value(42), allocator);       // 不能通过编译
a.PushBack(Value().SetInt(42), allocator); // fluent API
a.PushBack(Value(42).Move(), allocator);   // 和上一行相同

创建 String
RapidJSON 提供两个 String 的存储策略。

  1. copy-string: 分配缓冲区,然后把来源数据复制至它。
  2. const-string: 简单地储存字符串的指针。
//把一个 copy-string 赋值时
//调用含有 allocator 的 SetString() 重载函数
Document document;
Value author;
char buffer[10];
int len = sprintf(buffer, "%s %s", "Milo", "Yip");
author.SetString(buffer, len, document.GetAllocator());
memset(buffer, 0, sizeof(buffer));
// 清空 buffer 后 author.GetString() 仍然包含 "Milo Yip"

对于字符指针,RapidJSON 需要作一个标记,代表它不复制也是安全的。可以使用 StringRef 函数:

const char * cstr = getenv("USER");
size_t cstr_len = ...;                 // 如果有长度
Value s;
// s.SetString(cstr);                  // 这不能通过编译
s.SetString(StringRef(cstr));          // 可以,假设它的生命周期安全,并且是以空字符结尾的
s = StringRef(cstr);                   // 上行的缩写
s.SetString(StringRef(cstr, cstr_len));// 更快,可处理空字符
s = StringRef(cstr, cstr_len);         // 上行的缩写

Array 类型的 Value 提供与 std::vector 相似的 API。注意,Reserve(…) 及 PushBack(…) 可能会为数组元素分配内存,所以需要一个 allocator。

Clear()
Reserve(SizeType, Allocator&)
Value& PushBack(Value&, Allocator&)
template <typename T> GenericValue& PushBack(T, Allocator&)
Value& PopBack()
ValueIterator Erase(ConstValueIterator pos)
ValueIterator Erase(ConstValueIterator first, ConstValueIterator last)

4、使用字符串缓冲器生成——writer

#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include <iostream>
#include <string>using namespace std;void Serialize_1()
{rapidjson::StringBuffer strBuf;rapidjson::Writer<rapidjson::StringBuffer> writer(strBuf);writer.StartObject();//1. 整数类型writer.Key("Int");writer.Int(1);//2. 浮点类型writer.Key("Double");writer.Double(12.0000001);//3. 字符串类型writer.Key("String");writer.String("This is a string");//4. 结构体类型writer.Key("Object");writer.StartObject();writer.Key("name");writer.String("qq849635649");writer.Key("age");writer.Int(25);writer.EndObject();//5. 数组类型//5.1 整型数组writer.Key("IntArray");writer.StartArray();//顺序写入即可writer.Int(10);writer.Int(20);writer.Int(30);writer.EndArray();//5.2 浮点型数组writer.Key("DoubleArray");writer.StartArray();for(int i = 1; i < 4; i++){writer.Double(i * 1.0);}writer.EndArray();//5.3 字符串数组writer.Key("StringArray");writer.StartArray();writer.String("one");writer.String("two");writer.String("three");writer.EndArray();//5.4 混合型数组//这说明了,一个json数组内容是不限制类型的writer.Key("MixedArray");writer.StartArray();writer.String("one");writer.Int(50);writer.Bool(false);writer.Double(12.005);writer.EndArray();//5.5 结构体数组writer.Key("People");writer.StartArray();for(int i = 0; i < 3; i++){writer.StartObject();writer.Key("name");writer.String("qq849635649");writer.Key("age");writer.Int(i * 10);writer.Key("sex");writer.Bool((i % 2) == 0);writer.EndObject();}writer.EndArray();writer.EndObject();string data = strBuf.GetString();cout << data << endl;
}
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"void Serialize_2()
{rapidjson::Document doc;doc.SetObject();rapidjson::Document::AllocatorType& allocator = doc.GetAllocator();//1. 整型类型doc.AddMember("Int", 1, allocator);//2. 浮点类型doc.AddMember("Double", 12.00001, allocator);//3. 字符串类型//正确方式string str= "This is a string";rapidjson::Value str_value(rapidjson::kStringType);str_value.SetString(str.c_str(), str.size());if(!str_value.IsNull()){doc.AddMember("String", str_value, allocator);}/***    注:以下方式不正确,可能成功,也可能失败,因为字符串写入json要重新开辟内存,* 如果使用该方式的话,当数据是字符串常量的话是没问题的,如果为变量就会显示乱码,所* 以为保险起见,我们显式的分配内存(无需释放)*///doc.AddMember("String", str.data(), allocator);//4. 结构体类型rapidjson::Value object(rapidjson::kObjectType);object.AddMember("name", "qq849635649", allocator); //注:常量是没有问题的object.AddMember("age", 25, allocator);doc.AddMember("Object", object, allocator);//5. 数组类型//5.1 整型数组rapidjson::Value IntArray(rapidjson::kArrayType);IntArray.PushBack(10, allocator);IntArray.PushBack(20, allocator);IntArray.PushBack(30, allocator);doc.AddMember("IntArray", IntArray, allocator);//5.2 浮点型数组rapidjson::Value DoubleArray(rapidjson::kArrayType);DoubleArray.PushBack(1.0, allocator);DoubleArray.PushBack(2.0, allocator);DoubleArray.PushBack(3.0, allocator);doc.AddMember("DoubleArray", DoubleArray, allocator);//5.3 字符型数组rapidjson::Value StringArray(rapidjson::kArrayType);string strValue1 = "one";string strValue2 = "two";string strValue3 = "three";str_value.SetString(strValue1.c_str(), strValue1.size());StringArray.PushBack(str_value, allocator);str_value.SetString(strValue2.c_str(), strValue2.size());StringArray.PushBack(str_value, allocator);str_value.SetString(strValue3.c_str(), strValue3.size());StringArray.PushBack(str_value, allocator);doc.AddMember("StringArray", StringArray, allocator);//5.4 结构体数组rapidjson::Value ObjectArray(rapidjson::kArrayType);for(int i = 1; i < 4; i++){rapidjson::Value obj(rapidjson::kObjectType);obj.AddMember("name", "qq849635649", allocator);//注:常量是没有问题的obj.AddMember("age", i * 10, allocator);ObjectArray.PushBack(obj, allocator);}doc.AddMember("ObjectArray", ObjectArray, allocator);rapidjson::StringBuffer strBuf;rapidjson::Writer<rapidjson::StringBuffer> writer(strBuf);doc.Accept(writer);string data = strBuf.GetString();cout << data << endl;
}

RapidJSON入门:手把手教入门实例介绍相关推荐

  1. 编程语言python入门-手把手教你从零开始用Python语言写爬虫程序

    简单来说互联网是由一个个站点和网络设备组成的大网,我们通过浏览器访问站点,站点把HTML.JS.CSS代码返回给浏览器,这些代码经过浏览器解析.渲染,将丰富多彩的网页呈现我们眼前.如果我们把互联网比作 ...

  2. 新手入门手把手教你自学吉他,简单易懂看完就会

    0基础初学者和新手小白入门自学吉他,很简单看完就会. 记得之前的文章中好像说过,关于吉他的结构和各项功能自己买本书或者查资料很容易就能找到,思来想去还是想写一篇关于吉他0基础新手入门的内容,正好自己也 ...

  3. PyQt5入门——手把手教你配置环境,快速上手GUI程序开发(Anaconda+PyCharm+Qt Designer+pyuic)

    文章目录 引言 1. 安装python环境 1.1 安装anaconda 1.2 创建虚拟环境 2. 安装PyQt库 3. 安装pycharm 4. 在pycharm中配置PyQt 4.1 配置PyQ ...

  4. EGE 库入门——手把手教你从零完成 Flappy Bird 的编写

    文章目录 运行效果图 什么是 EGE 安装 EGE 下载 找到你的 MinGW 复制文件 测试 开始吧 获取素材 下载 Apktool 下载一个 FlappyBird.apk 开始解析 前置知识 图片 ...

  5. 数据库入门——手把手教你安装数据库

    1,网上搜索 SQL server 下载数据库 2,点击setup,安装--全新SQL server独立安装 3,勾选使用检查更新,点击下一步 4,默认选项不用管,直接点击下一步 5,点击下一步 6, ...

  6. Jmeter手把手教入门详细步骤,包括使用Jmeter进行Web,java模块测试

    进入公司实习,老大教给我的第一个任务就是学习Jmeter,然后给组里的人讲...只能一面懵逼的开始学习. Jmeter是什么? 我就不用官方的定义了,简单来说就是一个免费开源的软件,用于给服务器进行各 ...

  7. C# SuperSocket 手把手教你入门 傻瓜教程---1(服务器单向接收客户端发送数据)

    C# SuperSocket 手把手教你入门 傻瓜教程系列教程 C# SuperSocket 手把手教你入门 傻瓜教程---1(服务器单向接收客户端发送数据) C# SuperSocket 手把手教你 ...

  8. 网络编程懒人入门(八):手把手教你写基于TCP的Socket长连接

    转自即时通讯网:http://www.52im.net/ 本文原作者:"水晶虾饺",原文由"玉刚说"写作平台提供写作赞助,原文版权归"玉刚说" ...

  9. c++从入门到精通_资料下载:从入门到精通,手把手教你学DSP

    学习一个东西首先是了解它,比如DSP到底是什么?用在什么地方?怎么用?和单片机特点有那些相同与不同?开发需要注意什么?想了解清楚这些问题自然就清楚比较清楚的认识DSP.DSP,因为它是用来做数据处理, ...

最新文章

  1. python学习笔记-Day17(jinja2)
  2. 小菜的 VUE 使用技巧 持续更新
  3. tensorflow随笔-条件循环控制(4)
  4. Cpp 对象模型探索 / 类引入虚函数有哪些成本?
  5. Github 的清点对象算法
  6. 监督学习和无监督学习_一篇文章区分监督学习、无监督学习和强化学习
  7. getpriority java_Java Thread类的最终int getPriority()方法(带示例)
  8. python里none什么意思_Python 中None的用法
  9. offset,client,scroll的学习记录
  10. Confluence 6 审查日志的对象
  11. 《华为基本法》-笔记
  12. 可测空间、测度空间及σ-代数
  13. python捕捉warning_Python warnings.warn方法代码示例
  14. CentOS7如何升级ruby版本
  15. 一个开源「知乎日报」Android 客户端
  16. 极米H5值得入手吗?极米H5实际体验如何?画面对比实测
  17. html div 移除,js动态创建及移除div的方法
  18. RabbitMQ 开发时指定消息消费者的方式
  19. XT.COM直播间第109期 | CDT XT.COM AMA 专场
  20. 服务器硬盘插拔原理拆解,如何正确拆除在 ServeRAID适配器控制着的热插拔硬盘...

热门文章

  1. 宁可一思进 莫在一思停
  2. 浏览器打开的网页被恶意篡改的三种解决方式 个人总结的最全的方式,亲测有效
  3. 疫情下的学生管理系统
  4. 征程————学习之路
  5. 深度学习 - VGG16介绍及预训练神经网络的使用
  6. Fortify的安装使用
  7. 数学中的线性相关概念
  8. 【3.分页展示】查询只有key没有值及其他问题
  9. 怪”博士闵万里:用人工智能,解决吃饭出行问题
  10. Python 配置环境变量