分類

展開全部 | 收合全部

分類

展開全部 | 收合全部

【C++】C++ rapidjson 使用範例,產生 json 檔案的範本 cpp json template (內含範例程式碼) sample code

前言

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

⭐C++ 基礎用法 相關文章整理⭐:
1.【C++】C++ compile 程式碼 使用 c++ 11 與使用相關的 package
2.【C++】C/C++ 顯示資料的類別 (type) sample code (內含範例程式碼) print C data type, cout C++ data type, get variable type in c++
3.【C++】C++ 複製 2D array的方法 copy 2d array memcpy sample code (內含範例程式碼)
⭐Modern C++ ⭐:
⭐C++ 字串處理相關文章整理⭐:
1.【C++】字串 char string stringstream 相關用法總整理 (內含範例程式碼) 與利用 sprinf, snprinf assign 值的方法
2.【C++】字串 char string stringstream 「轉換」用法總整理 (內含範例程式碼)
3.【C】printf, fprintf, sprintf, snprintf 相關用法總整理 (內含範例程式碼)
4.【C++】C++ String 用法 連接兩個 String c++ string concat
⭐C++ 系統偵測相關文章整理⭐:
1.【C++】C++ 利用 dirent.h 計算資料夾的檔案數量 count files sample code (內含範例程式碼)
2.【C++】C++ inotify sample code 偵測指定路徑底下的文件變化 (內有範例程式碼)
⭐C++ OpenCV 相關文章整理⭐:
1.【OpenCV】c++ OpenCV – 在 ubuntu 上第一次執行 OpenCV 程式 sample code (內含範例程式碼)
2.【OpenCV】c++ OpenCV - 在圖片上寫上文字 cv::putText sample code (內含範例程式碼)
3.【OpenCV】c++ OpenCV - cv::Rect 矩形用法與相關功能函數 sample code (內含範例程式碼)
4.【OpenCV】c++ OpenCV - OpenCV 中的純量 定義顏色 cv::Scalar(255,255,255) color sample code (內含範例程式碼)
5.【OpenCV】用 C++ 計算 iou 的方法 與網路算法常見錯誤(內附範例程式碼) sample code
⭐C++ Makefile 相關文章整理⭐:
1.【C++ Makefile】- 1 / 嘗試撰寫自己的第一份 Makefile
2.【C++ Makefile】- 2 / 新增自己的變數
3.【C++ Makefile】- 3 / Makefile 常用變數 -「$@」, 「$^」
4.【C++ Makefile】- 4 / Makefile 常用 fake target -「.PHONY」
5.【C++ Makefile】- 5 / Makefile 內建變數 -「$@」, 「$^」, 「$<」, 「$* 」,「$? 」
⭐【喜歡我的文章嗎? 歡迎幫我按讚~ 讓基金會請創作者喝一杯咖啡!
如果喜歡我的文章,請幫我在下方【按五下Like】 (Google, Facebook 免註冊),會由 「LikeCoin」 贊助作者鼓勵繼續創作,讀者們「只需幫忙按讚,完全不用出錢」哦!

likecoin-steps
Howard Weng
Howard Weng

我是 Howard Weng,很多人叫我嗡嗡。這個網站放了我的各種筆記。希望這些筆記也能順便幫助到有需要的人們!如果文章有幫助到你的話,歡迎幫我點讚哦!
另外,因為定位是「個人的隨手筆記」,有些文章內容「⚠️可能我理解有誤⚠️」或「?只寫到一半?」,如果有發現這樣的情況,歡迎在該文章的最下面留言提醒我!我會儘快修正或補上!感謝大家的建議與幫忙,讓網站能變得更好?

文章: 883

★留個言吧!內容有誤或想要補充也歡迎與我討論!