前言
json 算是檔案與檔案溝通之間,非常經常使用的格式,
由於非常經常使用,我們將 json 製作檔案的格式紀錄下來,
供之後反覆使用方便。
範例程式碼
以下我們先分開說明每一種資料型態在 C++ rapidjson 處理的方式,
最後再整合起來,用一支程式進行全部的示範。
處理基本資料型態 (bool, int, double, string)
寫入 json (基本資料型態 bool, int, double, string)
Document json_content;
Document::AllocatorType& allocator = json_content.GetAllocator();
json_content.SetObject();
// set string, int, bool
json_content.AddMember("key1", "value1", allocator); // char*
// json_content.AddMember("key1", Value().SetString("value1".c_str(), allocator), allocator); // string
json_content.AddMember("key2", 10, allocator); // int
json_content.AddMember("key3", true, allocator); // bool
從 json 讀取 (基本資料型態 bool, int, double, string)
Document document; // Object (python dict)
document.Parse(json_content.str().c_str());
cout << "[Reading json content] document[key1] = " << document["key1"].GetString() << endl;
cout << "[Reading json content] document[key2] = " << document["key2"].GetInt() << endl;
cout << "[Reading json content] document[key3] = " << document["key3"].GetBool() << endl;
處理進階資料結構 – 1D Array (Python list)
這裡註記 Python list 的原因是因為作者本身是從 Python 學過來的XD,
由於資料結構命名不同,但指的是同樣的東西,因此在這邊做一些筆記。
寫入 json (1D Array)
// set array (python list)
// 1D array
Value oneDimArray(kArrayType);
for(int i = 0 ; i < 5; i++)
{
oneDimArray.PushBack(i, allocator);
}
json_content.AddMember("key4", oneDimArray, allocator);
從 json 讀取 (1D Array)
Value &value4 = document["key4"]; // array
assert(value4.IsArray() && "assertion error, value4 is not Array");
cout << "[Reading json content] document[key4] = " << endl;
cout << "[" ;
for(SizeType i = 0; i < value4.Size(); i++){
if(i < value4.Size() - 1)
cout << value4[i].GetInt() << ",";
else
cout << value4[i].GetInt() << "]\n";
}
處理進階資料結構 – 2D Array (Python list)
這裡註記 Python list 的原因是因為作者本身是從 Python 學過來的XD,
由於資料結構命名不同,但指的是同樣的東西,因此在這邊做一些筆記。
寫入 json (2D Array)
// set Value array (python list)
// 2D array
Value secondDimArray(kArrayType);
for(int j = 0 ; j < 5; j++){
Value firstDimArray(kArrayType);
for(int i = 0 ; i < 5; i++){
firstDimArray.PushBack(j*5+i, allocator);
}
secondDimArray.PushBack(firstDimArray, allocator);
}
json_content.AddMember("key5", secondDimArray, allocator);
從 json 讀取 (2D Array)
void printOneDimArray(Value &arr){
assert(arr.IsArray() && "assertion error, arr is not Array");
cout << "[" ;
for(SizeType i = 0; i < arr.Size(); i++){
if(i < arr.Size() - 1)
cout << arr[i].GetInt() << ",";
else
cout << arr[i].GetInt() << "]";
}
}
// read 2D array
cout << "[Reading json content] document[key5] = " << endl;
Value &value5 = document["key5"]; // array
cout << "[Reading json content] Get type of document[key5] = " << kTypeNames[document["key5"].GetType()] << endl; // kTypeNames[itr->value.GetType()]);
assert(value5.IsArray() && "assertion error, value5 is not Array");
cout << "[" ;
for(SizeType i = 0; i < value5.Size(); i++){
Value &eachArr = document["key5"][i]; // array
assert(eachArr.IsArray() && "assertion error, eachArr is not Array");
printOneDimArray(eachArr);
if(i < eachArr.Size() - 1)
cout << ",";
else
cout << "]";
}
cout << endl;
處理進階資料結構 – Object (Python dict)
寫入 json (Object – python dict)
// set Value Object (python dict)
// add sub_json_content to key6
Value sub_json_content(kObjectType);
// sub_json_content.AddMember("sub_key1", Value().SetString("sub_value1", allocator, allocator); // allocator = json_content.GetAllocator() // string
sub_json_content.AddMember("sub_key1", "sub_value1", allocator); // char*
sub_json_content.AddMember("sub_key2", 20, allocator); // int
sub_json_content.AddMember("sub_key3", false, allocator); // bool
json_content.AddMember("key6", sub_json_content, allocator);
從 json 讀取 (Object – python dict)
// Object (python dict)
cout << "[Reading json content] document[key6] = " << endl;
cout << "[Reading json content] Get type of document[key6] = " << kTypeNames[document["key6"].GetType()] << endl;
Value &value6 = document["key6"];
assert(value6.IsObject() && "assertion error, value6 is not Object");
cout << "[Reading json content] value6[sub_key1] = " << value6["sub_key1"].GetString() << endl;
cout << "[Reading json content] value6[sub_key2] = " << value6["sub_key2"].GetInt() << endl;
cout << "[Reading json content] value6[sub_key3] = " << value6["sub_key3"].GetBool() << endl;
範例程式碼
下面的範例是我們新增一份以 timestamp 作為檔案名稱的 json 檔案。
其他相關的變數:
基本功能設定
- root_folder:檔案根目錄
- Document make_json():json 的內容設定
- void generate_jsonfile(char* file_name, string json_content):產生對應的 json 檔案
- void read_jsonfile(char* file_name):讀取對應的 json 檔案
小工具
- string json_to_string(Document& d):(小工具) 以字串顯示 Document 格式的內容
- string json_to_string(Value& d):(小工具) 以字串顯示 Value 格式的內容
- int64_t timeMs():(小工具) 取得現在的 timestamp (13 位)
- void printOneDimArray(Value &arr):(小工具) 顯示一維的 Array 內容 (裡面有寫排版)
- static const char* kTypeNames[]:顯示資料型態的名稱,GetType() 所使用
#include "rapidjson/document.h" // error: ‘Document’ was not declared in this scope
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
// #include "rapidjson/prettywriter.h" // for stringify JSON
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <linux/limits.h>
// doc & tutorial:
// https://rapidjson.org/md_doc_tutorial.html
// http://rapidjson.org/zh-cn/index.html
// https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp
// Each JSON value is stored in a type called Value.
// A Document, representing the DOM, contains the root Value of the DOM tree.
// All public types and functions of RapidJSON are defined in the rapidjson namespace.
// ----------------------------
// Parse it into a Document:
// #include "rapidjson/document.h"
// using namespace rapidjson;
// // ...
// Document document;
// document.Parse(json);
// The JSON is now parsed into document as a DOM tree:
// ----------------------------
// Document, Value
// Value contains Object, Array
// Value Object = python dict
// Value Array = python list
using namespace std;
using namespace rapidjson;
static const char* kTypeNames[] =
{ "Null", "False", "True", "Object", "Array", "String", "Number" };
void printOneDimArray(Value &arr){
assert(arr.IsArray() && "assertion error, arr is not Array");
cout << "[" ;
for(SizeType i = 0; i < arr.Size(); i++){
if(i < arr.Size() - 1)
cout << arr[i].GetInt() << ",";
else
cout << arr[i].GetInt() << "]";
}
}
string json_to_string(Document& d){
StringBuffer buffer;
Writer<StringBuffer> writer(buffer); // PrettyWriter<StringBuffer> writer(buffer);
d.Accept(writer);
// cout << "[json_to_string (Document version)] json string = " << buffer.GetString();
return buffer.GetString();
}
string json_to_string(Value& d){
StringBuffer buffer;
Writer<StringBuffer> writer(buffer); // PrettyWriter<StringBuffer> writer(buffer);
d.Accept(writer);
// cout << "[json_to_string (Value version)] json string = " << buffer.GetString();
return buffer.GetString();
}
int64_t timeMs()
{
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return ((int64_t)time.tv_sec)*1000 + time.tv_nsec/1000000;
}
void read_jsonfile(char* file_name){
printf("[Reading json content] Reading json file: %s\n", file_name);
ifstream in(file_name);
string inputStr;
ostringstream json_content;
while(getline(in, inputStr)){
json_content << inputStr;
}
in.close();
cout << "[Reading json content] All json content = " << json_content.str() << endl;
Document document; // Object (python dict)
document.Parse(json_content.str().c_str());
cout << "[Reading json content] document[key1] = " << document["key1"].GetString() << endl;
cout << "[Reading json content] document[key2] = " << document["key2"].GetInt() << endl;
cout << "[Reading json content] document[key3] = " << document["key3"].GetBool() << endl;
// 1D array
Value &value4 = document["key4"]; // array
assert(value4.IsArray() && "assertion error, value4 is not Array");
cout << "[Reading json content] document[key4] = " << endl;
printOneDimArray(value4);
cout << endl;
// cout << "[" ;
// for(SizeType i = 0; i < value4.Size(); i++){
// if(i < value4.Size() - 1)
// cout << value4[i].GetInt() << ",";
// else
// cout << value4[i].GetInt() << "]\n";
// }
// 2D array
cout << "[Reading json content] document[key5] = " << endl;
Value &value5 = document["key5"]; // array
cout << "[Reading json content] Get type of document[key5] = " << kTypeNames[document["key5"].GetType()] << endl; // kTypeNames[itr->value.GetType()]);
assert(value5.IsArray() && "assertion error, value5 is not Array");
cout << "[" ;
for(SizeType i = 0; i < value5.Size(); i++){
Value &eachArr = document["key5"][i]; // array
assert(eachArr.IsArray() && "assertion error, eachArr is not Array");
printOneDimArray(eachArr);
if(i < eachArr.Size() - 1)
cout << ",";
else
cout << "]";
}
cout << endl;
// Object (python dict)
cout << "[Reading json content] document[key6] = " << endl;
cout << "[Reading json content] Get type of document[key6] = " << kTypeNames[document["key6"].GetType()] << endl; // kTypeNames[itr->value.GetType()]);
Value &value6 = document["key6"]; // object (python dict)
assert(value6.IsObject() && "assertion error, value6 is not Object");
cout << json_to_string(value6) << endl;
// cout << value6["sub_key1"] << endl;
cout << "[Reading json content] value6[sub_key1] = " << value6["sub_key1"].GetString() << endl;
cout << "[Reading json content] value6[sub_key2] = " << value6["sub_key2"].GetInt() << endl;
cout << "[Reading json content] value6[sub_key3] = " << value6["sub_key3"].GetBool() << endl;
}
void generate_jsonfile(char* file_name, string json_content){
// python
// with open(file_name, 'w') as f_out:
// ret = json.dumps(json_content)
// f_out.write(ret)
// printf("Generating file: %s\n", file_name);
FILE *f = fopen(file_name, "w");
if(f)
{
const char *s = json_content.c_str();
int r = fwrite(s, 1, strlen(s), f);
fclose(f);
printf("[Writing json content] Success to write file: %s\n", file_name);
}
else
{
printf("[Writing json content] Failed to write file: %s\n", file_name);
}
}
Document make_json(){
// tmp_ljob = {}
// tmp_ljob["key1"] = "value1"
// tmp_ljob["key2"] = "value2"
// tmp_ljob["key3"] = "value3"
// return tmp_ljob
Document json_content;
Document::AllocatorType& allocator = json_content.GetAllocator();
json_content.SetObject();
// set string, int, bool
json_content.AddMember("key1", "value1", allocator); // string
// json_content.AddMember("key1", Value().SetString("value1".c_str(), allocator), allocator); // string
json_content.AddMember("key2", 10, allocator); // int
json_content.AddMember("key3", true, allocator); // bool
// set array (python list)
// 1D array
Value oneDimArray(kArrayType);
for(int i = 0 ; i < 5; i++)
{
oneDimArray.PushBack(i, allocator);
}
json_content.AddMember("key4", oneDimArray, allocator);
// 2D array
Value secondDimArray(kArrayType);
for(int j = 0 ; j < 5; j++){
Value firstDimArray(kArrayType);
for(int i = 0 ; i < 5; i++){
firstDimArray.PushBack(j*5+i, allocator);
}
secondDimArray.PushBack(firstDimArray, allocator);
}
json_content.AddMember("key5", secondDimArray, allocator);
// set Document Object (python dict)
// add sub_json_content to key6
Value sub_json_content(kObjectType);
// sub_json_content.AddMember("sub_key1", Value().SetString("sub_value1", allocator, allocator); // allocator = json_content.GetAllocator()
sub_json_content.AddMember("sub_key1", "sub_value1", allocator); // string
sub_json_content.AddMember("sub_key2", 20, allocator); // int
sub_json_content.AddMember("sub_key3", false, allocator); // bool
json_content.AddMember("key6", sub_json_content, allocator);
return json_content;
}
int main(){
// prepare json
Document json_content = make_json();
Value tmpJsonObject(kObjectType);
tmpJsonObject.CopyFrom(json_content, json_content.GetAllocator());
cout << "[json_to_string] json_to_string = " << json_to_string(json_content) << endl; // document
cout << "[json_to_string] json_to_string = " << json_to_string(tmpJsonObject) << endl; // value
// d.SetObject();
// prepare filename (python)
// current_timestamp = int(time.time() * 1000) # 13 digits
// file_name = root_folder + "{:13d}.json".format(current_timestamp)
char buf_path[PATH_MAX];
string root_folder = "./";
int64_t current_timestamp = timeMs();
// printf("%ld\n", timeMs());
sprintf(buf_path, "%s/%ld.json", root_folder.c_str(), current_timestamp);
// printf("generating file: %s\n", buf_path);
// json_content = make_json()
generate_jsonfile(buf_path, json_to_string(json_content));
read_jsonfile(buf_path);
return 0;
}
執行結果
編譯 & 執行
g++ test_write_json.cpp && ./a.out
結果
[json_to_string] json_to_string = {"key1":"value1","key2":10,"key3":true,"key4":[0,1,2,3,4],"key5":[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19],[20,21,22,23,24]],"key6":{"sub_key1":"sub_value1","sub_key2":20,"sub_key3":false}}
[json_to_string] json_to_string = {"key1":"value1","key2":10,"key3":true,"key4":[0,1,2,3,4],"key5":[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19],[20,21,22,23,24]],"key6":{"sub_key1":"sub_value1","sub_key2":20,"sub_key3":false}}
[Writing json content] Success to write file: .//1642562237053.json
[Reading json content] Reading json file: .//1642562237053.json
[Reading json content] All json content = {"key1":"value1","key2":10,"key3":true,"key4":[0,1,2,3,4],"key5":[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19],[20,21,22,23,24]],"key6":{"sub_key1":"sub_value1","sub_key2":20,"sub_key3":false}}
[Reading json content] document[key1] = value1
[Reading json content] document[key2] = 10
[Reading json content] document[key3] = 1
[Reading json content] document[key4] =
[0,1,2,3,4]
[Reading json content] document[key5] =
[Reading json content] Get type of document[key5] = Array
[[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14],[15,16,17,18,19],[20,21,22,23,24]]
[Reading json content] document[key6] =
[Reading json content] Get type of document[key6] = Object
{"sub_key1":"sub_value1","sub_key2":20,"sub_key3":false}
[Reading json content] value6[sub_key1] = sub_value1
[Reading json content] value6[sub_key2] = 20
[Reading json content] value6[sub_key3] = 0
Reference
- https://rapidjson.org/md_doc_tutorial.html
- http://rapidjson.org/zh-cn/index.html
- https://github.com/Tencent/rapidjson/blob/master/example/tutorial/tutorial.cpp