rapidjson查询操作基本用法
程序员文章站
2024-02-02 18:31:16
...
博客搬家,原地址:https://langzi989.github.io/2017/05/27/rapidjson查询操作基本用法/
本系列文章以例子的方式进行呈现。
#include "rapidjson/document.h"
#include <iostream>
int main()
{
const char* test = "{\"num\":123, \"hello\":null, \"type\": \"object\",\"properties\": {\"oid\": {\"type\": \"string\"}, \"username\": {\"type\": \"string\"},\"creid\": {\"type\": \"string\"}},\"required\": [\"oid\", \"username\",\"creid\"]}";
rapidjson::Document document;
//Parse(const char*). 从c-string解析为Document json格式
document.Parse(test);
//GetString().从Document json中取出string
std::cout << "type = " << document["type"].GetString() << std::endl;
/* 函数原型 函数功能
* IsNull() 判断当前键对应的值是不是null
* IsNumber() 判断当前键对应的值是不是number
* IsInt() 判断当前键对应的值是不是int
* IsDouble() 判断当前键对应的值是不是double
* IsString() 判断当前键对应的值是不是string
* IsBool() 判断当前键对应的值是不是bool
* IsArray() 判断当前键对应的值是不是array
* ...
*/
std::cout << "hello is " << (document["hello"].IsNull() ? "null" : "not null") << std::endl;
std::cout << "num is " << (document["num"].IsNumber() ? "number" : "not number") << std::endl;
std::cout << "required is " << (document["required"].IsArray()? "array" : "not array") << std::endl;
/* 访问Array的两种方法
* 1. 通过下标访问 //使用引用来连续访问,方便之余还更高效。
* 2. 通过迭代器访问
* 注意问题
* 1.索引使用SizeType类型,而不是size_t类型,缺省情况下,SizeType是unsigned的typedef
* 2.对于String类型使用GetInt是非法的,这个时候会导致程序崩溃
*/
const rapidjson::Value &a = document["required"];
assert(a.IsArray());
for (rapidjson::SizeType i = 0; i < a.Size(); i++)
std::cout << a[i].GetString() << std::endl;
for (rapidjson::Value::ConstValueIterator it = a.Begin(); it != a.End(); it++) {
std::cout << it->GetString() << std::endl;
std::cout << it->GetStringLength() << std::endl;
}
/* 访问object的方法
* 1.使用迭代器进行访问
* 2.使用键对应的下标进行当问 如:document["required"]
* 注意问题
* 1.在使用下标访问之前,最好先调用HasMember()检查一下当前键是否存在,若存在再往下继续。否则会出现段错误。
*/
static const char* kTypeNames[] = {"Null", "False", "True", "Object", "Array", "String", "Number"};
for (rapidjson::Value::ConstMemberIterator it = document.MemberBegin();
it != document.MemberEnd(); it++) {
std::cout << it->name.GetString() << " is type : " << kTypeNames[it->value.GetType()] << std::endl;;
}
/* 查询Number
* 说明:Json只提供一种数值类型---Number。Number可以是实数也可以是整数
* Dom提供了5中数值类型。包括unsigned,int,uint_64,int_64,double
* 类型检查 数值提取
* IsUint() GetUint()
* IsInt() GetInt()
* IsUint64() GetUint64()
* IsInt64() GetInt64()
* IsDouble() GetDouble()
*
* 查询String
* 说明:除了getString(), Value类也有一个GetStringLength();原因是rapidjson的String需要支持Unicode字符,如\u0000.问题是C/C++字符串是
* 空字符结尾的字符串,,这种字符串会把'\0'作为结束符号。为了符合RFC4627,若要处理这些带有unicode的字符串,
* 需要使用GetStringLength获取正确的字符串长度
* 函数 功能
* const char* getString() 获取C字符串
* SizeType GetStringLength()const 获取字符串的长度,
*/
rapidjson::Document d1;
d1.Parse("{\"s\":\"a\\u0000b\", \"num\":123}");
std::cout << d1["s"].GetString() << std::endl;
std::cout << d1["s"].GetStringLength() << std::endl;
std::cout << strlen(d1["s"].GetString()) << std::endl;
/*
* 比较两个Value的值
* 1.使用==和!=比较两Value的值,当且仅当两个Value的类型和内容相等才算相等。
* 2.可以将Value与原始值进行比较
* 3.若被比较的两个Value的类型不同,直接返回false。
* 4.可以比较不同Object的值
*/
std::cout << (document["num"] == document["hello"]) << std::endl;
std::cout << (document["num"] == d1["num"]) << std::endl;
/*
* 创建/修改值
* 1.改变Value的类型:当使用默认构造函数创建一个Value或者Document的时候,它的类型默认为
* NULL,要改变其类型,使用SetXXX()。如
* rapidjsons::Document d;
* d.SetObject(); //将d的类型修改为Object
* rapidjson::Value v;
* v.SetInt(1); //或者v = 1;
* 2.构造函数的重载
* rapidjson::Value b(false);
* rapidjson::Value n(10);
*
* 3.特别注意Value的转移语义。 Value重载operator=()时使用了转移语义。
* rapidjson::Value a(123);
* rapidjson::Value b(456);
* a = b; //此时b变为null,a为456
* 4.使用move()函数实现函数参数中的转移语义
* rapidjson::Value a(0);
* test(a.move());
*
*/
rapidjson::Value testa(10);
rapidjson::Value testb(10);
testa = testb;
std::cout << testa.GetInt() << std::endl;
if (testb.IsNull())
{
std::cout << "testb is moved to a, and now testb is null" << std::endl;
}
else
{
std::cout << testb.GetInt() << std::endl;
}
/*
* 创建String
* rapidjson提供两种string的存储策略:
* 1.copy-string(深拷贝):分配缓冲区,然后把来源数据复制至它
* 2.const-string(浅拷贝):简单的存储字符串指针
* 说明:
* 1.copy-string总是安全的,因为它拥有数据的克隆
* 2.当数据源发生改变,const-string中的数据也会受到影响
* 上面两种字符串的创建方式:
* 1.copy-string创建方式需要给API传递一个Allocator参数,这个做法避免了给每一个
* Value都保存一个Allocator。另外还需要一个length参数,保存长度信息,故
* 此函数可以处理带有空字符的字符串。
* 2.const-string创建方式不需要长度信息和Allocator参数,它默认字符串以\0结束.
* 一般用于常量字符串或者具有安全生存周期的字符串上
*/
rapidjson::Value autor;
char buffer[50];
int len = sprintf(buffer, "%s %s", "Milo", "Yip");
autor.SetString(buffer,len, document.GetAllocator());
memset(buffer, 0x0, sizeof(buffer));
std::cout << autor.GetString() << std::endl;
rapidjson::Value testString;
testString = "testString";
std::cout << testString.GetString() << std::endl;
/** 修改Array
* 函数 功能
* clear() 清空Array中的内容
* 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) 删除指定范围元素
*/
rapidjson::Value testArray(rapidjson::kArrayType);
rapidjson::Document::AllocatorType& testAllocator = document.GetAllocator();
for (int i = 0; i < 5; i++)
{
testArray.PushBack(i, testAllocator);
}
testArray.PushBack("lua", testAllocator).PushBack("Mio", testAllocator);
for (rapidjson::SizeType i = 0;i < 5; i++)
std::cout << testArray[i].GetInt() << std::endl;
std::cout << testArray[5].GetString() << std::endl;
std::cout << testArray[6].GetString() << std::endl;
/* 修改Object
* 说明:每个Object都是键值对的集合。每个键必须为String。
* 添加成员的函数:
* 1.Value& AddMember(Value&, Value&, Allocator& allocator)
* 2.Value& AddMember(StringRefType, Value&, Allocator&)
* 3.template <typename T> Value& AddMember(StringRefType, T value, Allocator&)
*
* 补充说明:1.使用StingRefType作为name参数的重载版本与字符串的SetString()类似。这些重载是为了避免复制name字符串
* 因为jsonObject中经常会使常数键名。
* 2.如果你需要从非常数字符串或者生命周期不足的字符串创建键名,需要使用copy-string API。
* 为了避免中间变量,可以使用临时值
*
* 移除成员函数:
* 1.bool RemoveMember(const Ch* name):使用键名来移除成员(线性时间复杂度)。
* 2.bool RemoveMember(const Value& name):除了 name 是一个 Value,和上一行相同。
* 3.MemberIterator RemoveMember(MemberIterator):使用迭代器移除成员(_ 常数 _ 时间复杂度)。
* 4.MemberIterator EraseMember(MemberIterator):和上行相似但维持成员次序(线性时间复杂度)。
* 5.MemberIterator EraseMember(MemberIterator first, MemberIterator last):移除一个范围内的成员,维持次序(线性时间复杂度)。
*/
rapidjson::Value contact(rapidjson::kObjectType);
contact.AddMember("name", "milo", document.GetAllocator());
contact.AddMember("married", false, document.GetAllocator());
std::cout << "contact[name] is:"<<contact["name"].GetString() << std::endl;
std::cout << "contact[married] is:" << contact["married"].GetBool() << std::endl;
contact.AddMember(rapidjson::Value("copy", document.GetAllocator()).Move(), // copy string
rapidjson::Value().Move(), // null value
document.GetAllocator());
/* 深复制Value
* 方法:
* 1.含有Allocator的构造函数
* 2.含有Allocator的CopyFrom
* 交换Value
* 方法: Swap() 无论两颗Dom树多复杂,交换时间为常数
*/
rapidjson::Value testCopy1(123);
rapidjson::Value testCopy2(testCopy1, document.GetAllocator());
rapidjson::Value testCopy3;
testCopy3.CopyFrom(testCopy1, document.GetAllocator());
testCopy1.Swap(testCopy3);
}
上一篇: C语言 > 分解质因数
推荐阅读
-
rapidjson查询操作基本用法
-
MySQL联表查询基本操作之left-join常见的坑
-
6、基本查询操作_MySQL
-
PHP操作Excel – PHPExcel 基本用法详解_PHP教程
-
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
-
Python中的MongoDB基本操作:连接、查询实例
-
HTML5本地存储localStorage、sessionStorage基本用法、遍历操作、异常处理等
-
MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询
-
IOS开发中NSURL的基本操作及用法详解
-
iOS开发中使用SQL语句操作数据库的基本用法指南