rapidjson创建型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include <string>
using namespace std;
using namespace rapidjson;
int main() {
Document d;
d.SetObject();
std::string s = "123";
rapidjson::Document::AllocatorType& allocator = d.GetAllocator();
//生成含有数组的document,注意在rapidjson中所有的数据都是一个Value,数组的本质也是一个Array;
rapidjson::Value arr(rapidjson::kArrayType);
arr.PushBack("1", allocator);
arr.PushBack("2", allocator);
arr.PushBack(rapidjson::StringRef(s.c_str()), allocator);
//生成数组中包含有多个obj的数组
rapidjson::Value o1;
o1.SetObject();
o1.AddMember("o1", 1, allocator);
arr.PushBack(o1, allocator);
rapidjson::Value o2;
o2.SetObject();
o2.AddMember("o2", 2, allocator);
arr.PushBack(o2, allocator);
d.AddMember("arr", arr, allocator);
rapidjson::StringBuffer buffer;
rapidjson::Writer<StringBuffer> writer(buffer);
d.Accept(writer);
std::cout << buffer.GetString() << std::endl;
return 0;
}

Comment and share

rapidjson Stream(待更新)

本系列文章以例子的方式进行呈现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "rapidjson/filereadstream.h"
#include "cstdio"
using namespace std;
using namespace rapidjson;
int main() {
const char json[] = "[1, 2, 3]";
StringStream s(json);
Document document;
document.ParseStream(s);
for (int i = 0; i < 3; i++)
std::cout << document[i].GetInt() << std::endl;
StringBuffer SB;
Writer<StringBuffer> writer(SB);
document.Accept(writer);
std::cout << SB.GetString() << std::endl;
FILE* fp = fopen("test.json", "rb");
char readBuffer[65535];
FileReadStream is(fp, readBuffer, sizeof(readBuffer));
document.ParseStream(is);
fclose(fp);
for (Value::ConstMemberIterator it = document.MemberBegin();
it != document.MemberEnd(); it++)
std::cout << (it->name).GetString() << std::endl;
}

Comment and share

rapidjson Schema

本系列文章以例子的方式进行呈现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/*
* JsonSchema本质上是一个json,其作用是用于校验Json,使用schema对json进行校验,
* 可以让代码安全的去当问DOM,而不需要去检查类型或者键值的存在等等。这也能确保输
* 出的json符合特定的schema。
*/
#include "rapidjson/schema.h"
#include "rapidjson/stringbuffer.h"
#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;
using namespace rapidjson;
/*使用JsonSchema校校验json格式的流程:
* 1. 将schema(模板)解析成一个Document
* 2. 然后将Document编译成一个SchemaDocument
* 3. 通过上述SchemaDocument创建一个SchemaValidator。
* 4. 然后通过document.Accept(validator)去校验一个json,获取校验结果。
*注意:
* 1. 一个SchemaDocument能被多个SchemaValidator引用,他不会被SchemaValidator修改。
* 2. 可以重复使用SchemaValidator校验多个文件。在校验其他文件之前,必须先调用validator.Reset()。
*JsonSchema的格式:
* 1. JsonSchema实质上是一个json数据。
* 2. JsonSchema与其他json数据不同的是它在每一个对象和元素中定义了他们的类型type,属性(如object的properties,以及integer的minimum等等),
* 同时,我们可以通过JsonSchema对json的值的类型以及取值范围等进行限定。schema中必须的值需要显示的声明在required中。
*/
bool ValidateJson() {
string testSchema = "{\"type\":\"object\", \"properties\":{\"code\":{\"type\":\"string\"}, \"int\":{\"type\":\"integer\", \"minimum\":0}}, \"required\":[\"int\",\"code\"]}";
Document sd;
if (sd.Parse(testSchema.c_str()).HasParseError()) {
printf("jsonSchema is not valid : %s", testSchema.c_str());
return false;
}
//创建SchemaDocument
SchemaDocument schema(sd);
Document d;
if (d.Parse("{\"code\":123, \"int\":1}").HasParseError()) {
printf("Document is not a valid json");
return false;
}
SchemaValidator validator(schema);
if (!d.Accept(validator)) {
StringBuffer sb;
validator.GetInvalidSchemaPointer().StringifyUriFragment(sb);
printf("Invalid schema: %s\n", sb.GetString());
printf("Invalid keyword: %s\n", validator.GetInvalidSchemaKeyword());
sb.Clear();
validator.GetInvalidDocumentPointer().StringifyUriFragment(sb);
printf("Invalid document:%s\n ", sb.GetString());
return false;
} else {
printf("符合schemas模式\n");
return true;
}
}
int main() {
ValidateJson();
}

Comment and share

rapidjson指针

本系列文章以例子的方式进行呈现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "rapidjson/document.h"
#include "rapidjson/pointer.h"
#include <iostream>
using namespace rapidjson;
/*
* Json Pointer
* 一个Json Pointer有一串(0至多个)token所组成,每个token之前都有/前缀。每个token
* 可以是字符串或者数字。例如,给定一个json:{
* "foo":["bar", "baz"],
* "pi":3.414
* }
* JsonPointer解析为:
* 1. "/foo"->["bar", "baz"]
* 2."/foo/0"->"bar"
* 3."/foo/1"->"baz"
* 4."pi"->3.414
* 特别注意:一个空Json Pointer""解析为整个json
*/
int main()
{
Document d;
/* 创建、修改、访问dom元素
* 创建dom元素的方法: (两种都可以自动生成父值,可以同时创建几级)
* 1.Pointer("/Key").Set(document, "value"); key对应值为value
* 2.Pointer("/Key").Create(document). 此时创建出来的key对应的值为null
* 获取Dom元素的pointer:
* 1.Value* vptr = Pointer("/Key").Get(document)
* 2.Value& vref = Pointer("/Key").GetWithDefault(document, "defaultValue");
* 注意返回的是引用,如值不存在,则创建此键并深拷贝默认值。
* 交换:
* Pointer("/Key").Swap(document, value); //注意交换的是Value,不能为其他类型
* 删除:
* Pointer("/Key").Erase(document);
*/
/* 针对上述函数的辅助函数
* SetValueByPointer(document, "/Key", "KeyValue");
* CreateValueByPointer(document, "/Key");
* GetValueByPointer(document, "/Key");
* GetValueByPointerWithDefault(document, "/default", "defaultValue");
* SwapValueByPointer(document, "/Key", Value); //必须为Value
* EraseValueByPointer(document, "/Key");
*/
/* Pointer相关函数说明
* 1.Pointer::Get() 或 GetValueByPointer() 函数并不修改 DOM。
* 若那些 token 不能匹配 DOM 里的值,这些函数便返回 nullptr。
* 使用者可利用这个方法来检查一个值是否存在。
* 2. Create()、GetWithDefault()、Set()、Swap()都会改变Dom.
* 若一些父值不存在,就会创建它们。若父值类型不匹配 token,
* 也会强行改变其类型。改变类型也意味着完全移除其 DOM 子树的内容
*/
/*
* Pointer中负号解析
* 1.在Get中,负号永远都是Key的名字
* 2.在Set中,若负号在数组的后面,则表示数组最后一个元素的下一个
* 否则表示数组名。例:
* d.Parse("{\"foo\":[123]}");
* SetValueByPointer(d, "/foo/-", 456); // { "foo" : [123, 456] }
* SetValueByPointer(d, "/-", 789); // { "foo" : [123, 456], "-" : 789 }
*/
/* 字符串化
* 可以将一个Pointe字符串化,存储于字符串或者其他输出流。
* 如:
* Pointer p(...);
* StringBuffer sb;
* p.StringFy(sb);
* std::cout << sb.GetString() << std::endl;
*/
Pointer("/project").Set(d, "RapidJson");
Pointer("/stars").Set(d, 10);
std::cout << d["project"].GetString() << std::endl;
std::cout << d["stars"].GetInt() << std::endl;
if (Value* stars = Pointer("/stars").Get(d))
{
stars->SetInt(stars->GetInt() + 1);
}
std::cout << d["stars"].GetInt() << std::endl;
Pointer("/default").GetWithDefault(d, "defaultValue");
if (d.HasMember("default"))
std::cout << d["default"].GetString() << std::endl;
Value swapValue("SwapValue");
Pointer("/default").Swap(d, swapValue);
std::cout << d["default"].GetString() << std::endl;
Pointer("/default").Erase(d);
if (!d.HasMember("default"))
std::cout << "d Erase default successful" << std::endl;
}

Comment and share

rapidjson查询操作基本用法

本系列文章以例子的方式进行呈现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#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);
}
`

Comment and share

  • page 1 of 1

魏传柳(2824759538@qq.com)

author.bio


Tencent


ShenZhen,China