json for modern c++的使用

2021-02-21 CPP開發者

(給CPP開發者加星標,提升C/C++技能)

導讀:json是一種十分常見的數據交換格式,在接口中被廣泛使用。很多高級語言如python等都對json有良好的支持,方便程式設計師的使用。


然而C++對json沒有很好的內置支持,因此往往要引用一些第三方庫。而網上很多json的包,形形色色種類繁多,但是要麼功能不夠強大,要麼難以使用。


json for modern c++是一款非常好用的json庫,具有語法直觀和使用簡單的特點,並且是用C++11標準編寫的,此外還支持STL和json容器之間的轉換,可謂集方便又強大。


本文推薦給廣大C++程式設計師,相信學習完本文之後,在處理json時一定會得心應手。

————【以下是正文】————   

最近學習了json for modern c++的使用,在此總結一些常用功能使用方法。
老規矩,還是先簡單介紹一下什麼是json吧。

JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。它基於ECMAScript的一個子集。JSON採用完全獨立於語言的文本格式,但是也使用了類似於C語言家族的習慣(包括C、C++、C#、Java、JavaScript、Perl、Python等)。這些特性使JSON成為理想的數據交換語言。易於人閱讀和編寫,同時也易於機器解析和生成(一般用於提升網絡傳輸速率)。


今天介紹的json版本是在c++下使用的,是一個開源項目。


GitHub開源項的地址:https://github.com/nlohmann/json


json for modern c++是一個德國大牛nlohmann寫的,該版本的json有以下特點:


1.直觀的語法。
2.整個代碼由一個頭文件組成json.hpp,沒有子項目,沒有依賴關係,沒有複雜的構建系統,使用起來非常方便。
3.使用c++11標準編寫。
4.使用json 像使用STL容器一樣。
5.STL和json容器之間可以相互轉換。

如何使用?

將github上的src文件夾裡的json.hpp頭文件下載保存到當前目錄中。
在代碼中包含json.hpp頭文件並引入json作用域

#include "json.hpp"using json = nlohmann::json;

常用功能:一.創建json對象

1.使用cin,cout輸入輸出流。
json提供了cin,cout的輸入輸出流的操作符。但需要注意的是,cin要有ctr + D結束輸入。cin會把從標準輸入的內容反序列化,cout會自動把json序列化,以string形式輸出。

using namespace std;using json=nlohmann::json;
int main(){ json j; //創建json類 cin>>j; //從cin讀入json對象 cout<<j; //輸出序列化的json return 0;}
/*輸入:{ "pi": 3.141, "happy": true, "name": "Niels", "nothing": null, "answer": { "everything": 42 }, "list": [1, 0, 2], "object": { "currency": "USD", "value": 42.99 }}輸出:{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}*/

2.提供根據鍵直接生成鍵值對的方法。(類似於map,如果不存在該鍵的話,就生成一個這個鍵。)

using json = nlohmann::json;using namespace std;
int main() { // 創建一個json對象(null) json j;
//添加一個存儲為double的數字 j["pi"] = 3.141;
// 添加一個布爾值 j["happy"] = true;
// 添加一個存儲為std :: string的字符串 j["name"] = "Niels";
// 通過傳遞nullptr添加另一個空對象 j["nothing"] = nullptr;
// 在對象中添加對象 j["answer"]["everything"] = 42;
//添加一個數組,其存儲為std::vector(使用初始化列表) j["list"] = { 1, 0, 2 };
// 在一個對象中添加另一個對象 j["object"] = { {"currency", "USD"}, {"value", 42.99} };
// 也可以通過直接賦值方式創建json對象,兩種方式創建結果相同 json j2 = { {"pi", 3.141}, {"happy", true}, {"name", "Niels"}, {"nothing", nullptr}, {"answer", { {"everything", 42} }}, {"list", {1, 0, 2}}, {"object", { {"currency", "USD"}, {"value", 42.99} }} }; cout << j << endl; cout << endl; cout << j2 << endl; return 0;}
/*輸出:{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}

{"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}*/

3.在所有上述情況下,你不需要「告訴」編譯器要使用哪個JSON值。如果你想明確或表達一些邊緣的情況下,可以使用json::array,json::object。

#include <iostream>#include "json.hpp"using json = nlohmann::json;using namespace std;
int main() { json empty_array_explicit = json::array();
json empty_object_implicit = json({}); json empty_object_explicit = json::object();}

4.幾點注意
1).array是一個數組,可以用數字直接下標訪問。

json array = {        "a",6,"xin",8    };cout << array[0] << endl;

2)數組中包含一個數組

json array = {        {"a",6},        "xin",8    };cout << array[0][0] << endl;  

3)數組中包含一個對象

json array = {        {{"a",6}},        "xin",8    };cout << array[0]["a"] << endl;

4).對象中嵌套一個對象和一個數組

json object = {        {"a",{{"feng",6}}},{"b",{1,2,3}}    };    cout << object << endl;

二.序列化

將json對象序列化,成為字符串

1.標準輸出自動序列化

json jstd :: cout << j;std :: cout << std :: setw( 4)<< j << std :: endl;

2.使用dump()函數

//顯式轉換為string std::string s = j.dump();    // {\"happy\":true,\"pi\":3.141}
//序列化與漂亮的列印//傳入空格的數量縮進 std::cout << j.dump(4) << std::endl;// 輸出://{// "happy": true,// "pi": 3.141// }

三.反序列化

將數據流轉化為json對象

1.從標準輸入反序列化

2.通過附加_json到字符串文字來創建對象(反序列化):

json j = " { \" happy \":true,\" pi \":3.141} " _json;
auto j2 = R"( { "happy":true, "pi":3.141 } )" _json;

請注意,沒有附加_json後綴,傳遞的字符串文字不會被解析,而只是用作JSON字符串值。也就是說,json j = "{ \"happy\": true, \"pi\": 3.141 }"只存儲字符串"{ "happy": true, "pi": 3.141 }"而不是解析實際的對象。

3.使用json::parse()函數

auto j3 = json::parse(" { \" happy \":true,\" pi \":3.141} ");

4.從迭代器範圍讀取

您還可以從迭代器範圍讀取JSON; 也就是說,可以從其內容存儲為連續字節序列的迭代器訪問的任何容器,例如std::vector

std :: vector < uint8_t > v = { ' t ',' r ',' u ',' e ' };json j = json :: parse(v.begin(),v.end());
//或std :: vector < uint8_t > v = { ' t ',' r ',' u ',' e ' };json j = json :: parse(v);

四.與STL適應

nlohmann設計的JSON類,就像一個STL容器一樣。其實它滿足了可逆容器要求。

json j;j.push_back("foo");j.push_back(1);j.push_back(true);
j.emplace_back(1.78);
for (json::iterator it = j.begin(); it != j.end(); ++it) { std::cout << *it << '\n';}
for (auto& element : j) { std::cout << element << '\n';}
const std::string tmp = j[0];j[1] = 42;bool foo = j.at(2);
j == "[\"foo\", 1, true]"_json;
j.size(); j.empty(); j.type(); j.clear();
j.is_null();j.is_boolean();j.is_number();j.is_object();j.is_array();j.is_string();
json o;o["foo"] = 23;o["bar"] = false;o["baz"] = 3.141;
o.emplace("weather", "sunny");
for (json::iterator it = o.begin(); it != o.end(); ++it) { std::cout << it.key() << " : " << it.value() << "\n";}
if (o.find("foo") != o.end()) { }
int foo_present = o.count("foo"); int fob_present = o.count("fob");
o.erase("foo");

五.從STL容器轉換

任何序列容器(std::array,std::vector,std::deque,std::forward_list,std::list),其值可以被用於構建JSON類型(例如,整數,浮點數,布爾值,字符串類型,或者再次在本節中描述STL容器)可被用於創建JSON陣列。這同樣適用於類似的關聯容器(std::set,std::multiset,std::unordered_set,std::unordered_multiset),但是在這些情況下,陣列的元素的順序取決於元素是如何在各個STL容器排序。

std::vector<int> c_vector {1, 2, 3, 4};json j_vec(c_vector);
std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6};json j_deque(c_deque);
std::list<bool> c_list {true, true, false, true};json j_list(c_list);
std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};json j_flist(c_flist);
std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};json j_array(c_array);
std::set<std::string> c_set {"one", "two", "three", "four", "one"};json j_set(c_set);
std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};json j_uset(c_uset);
std::multiset<std::string> c_mset {"one", "two", "one", "four"};json j_mset(c_mset);
std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};json j_umset(c_umset);

同樣,任何鍵值容器(std::map,std::multimap,std::unordered_map,std::unordered_multimap),其鍵可以構造一個std::string,並且其值可以被用於構建JSON類型(參見上文實施例)可用於創建一個JSON對象。請注意,在多重映射的情況下,JSON對象中僅使用一個鍵,該值取決於STL容器的內部順序。

<br>std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };json j_map(c_map);
std::unordered_map<const char*, double> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };json j_umap(c_umap);
std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };json j_mmap(c_mmap);
std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };json j_ummap(c_ummap);

六.隱式轉換

JSON對象的類型由要存儲的表達式自動確定。同樣,存儲的值被隱式轉換。

<br>std :: string s1 = 「 Hello,world!」 ;json js = s1;std :: string s2 = js;
bool b1 = true ;json jb = b1;bool b2 = jb;
int i = 42 ;json jn = i;double f = jn;

還可以明確要求該值:

std :: string vs = js.get <std :: string>();bool vb = jb.get < bool >();int vi = jn.get < int >();

七.任意類型轉換

每個類型都可以以JSON序列化,而不僅僅是STL容器和標量類型。通常情況下,你會做這些事情:

namespace ns {    struct person {        std::string name;        std::string address;        int age;    };}
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
json j;j["name"] = p.name;j["address"] = p.address;j["age"] = p.age;

ns::person p { j["name"].get<std::string>(), j["address"].get<std::string>(), j["age"].get<int>()};

或者,使用一種更簡便的用法

ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};
json j = p;
std::cout << j << std::endl;
ns::person p2 = j;
assert(p == p2);

以上是對json for modern c++基本功能的使用總結,如有哪裡有誤,歡迎指出,相互學習交流。

- EOF -

覺得文章不錯,請點讚和在看支持我繼續分享好文。謝謝!

關注『CPP開發者』

看精選C++技術文章 . 加C++開發者專屬圈子

↓↓↓

點讚和在看就是最大的支持❤️

相關焦點

  • Python 標準庫之 JSON
    +'),'age':23}]>>> data[{'name': 'rocky', 'like': ('python', 'c++'), 'age': 23}]>>> data_json = json.dumps(data)>>> data_json'[{"name": "rocky", "like": ["
  • 使用JSONObject生成和解析json
    中不區分整數、小數等類型,而統一使用Number來存儲數字。構建json在eclipse中使用JSONObject需要引用org.json包,推薦通過maven引用,如果不會使用maven,搭建maven項目可參考這篇文章《使用Eclipse構建Maven項目 (step-by-step)》,引用json則參考這篇文章《maven引入json各種版本》。
  • 在Python中使用JSON
    引入json模塊要使用JSON(字符串或包含JSON對象的文件),你可以使用Python的json模塊。在使用該模塊之前,需要先引入它。例2: 使用Python讀取JSON 文件你可以使用json.load()方法讀取一個包含JSON對象的文件。假設你有一個名為person.json的文件,它包含一個JSON對象。
  • Go:使用json時的陷阱
    但其中有一些根本沒有在文檔中提到,或者至少沒有明確指出-值得注意!>注意,如果使用其他類型作為map的鍵進行編碼將會得到一個json.UnsupportedTypeError錯誤。例如:func main() { m := []float64{ 123.0, 456.100, 789.990, } marshal, _ := json.Marshal(m) fmt.Println(string(marshal))}
  • Python中json模塊的使用介紹
    # json:數據交換用到json文件,json是特殊的字符串,一種輕量級的數據交換格式# json 本質就是字符串,區別在於
  • 使用Python附加到JSON文件
    JSON的完整形式是JavaScript Object Notation。
  • Python如何操作Json?本文也許能幫到您!
    json的數據格式在json中,遵循「鍵值對」的這樣一種方式,比如:「{"name":"tom"}」,就是一個json格式的數據,json的格式歸納下來,一般有以下幾點:對象通過鍵值對表現;鍵通過雙引號包裹,後面跟冒號「:」,然後跟該鍵的值;值可以是字符串、數字、數組等數據類型;對象與對象之間用逗號隔開;「{}」用來表達對象;「[]」用來表達數組
  • 如何在Python中使用JSON數據
    因此,任何程式語言都可以使用它。它用於存儲和交換數據。例如,從API提取數據或在某些文檔資料庫中使用數據時,數據大多採用JSON格式。讓我們舉個例子。 Python具有對JSON的本地支持,並為此提供了內置模塊json。在代碼頂部添加以下行以開始使用JSON。首先,讓我們看一下如何執行序列化,即編碼JSON數據。
  • php中使用json_decode()和json_encode()
    eg:$book = array('a'=>'lzichun','b'=>'nihao','c'=>'wohenhao','d'=>'ljlong');$json = json_encode($book);echo $json;{"a":"lzichun","b":"nihao
  • 教程 | C# 使用Newtonsoft.Json讀寫Json文件
    );//讀取文件JObject jobject = JObject.Parse(jsonString);//解析成jsonjobject["Information"][0]["LocationName"] = "通道1";//替換需要的文件string convertString = Convert.ToString(jobject);//將json裝換為string
  • 使用Python讀取,寫入和解析JSON
    為了處理JSON數據,Python有一個名為的內置包json。() 方法可以解析json字符串,結果將是Python字典。在這裡,我們已使用該open()函數讀取JSON文件。然後,使用json.load()提供給我們一個名為data的字典的方法來解析文件。從Python轉換為JSONjson.dumps() 方法可以將Python對象轉換為JSON字符串。
  • 在Go語言中,怎樣使用Json的方法?
    (jsonBlob, &animals) if err != nil {  fmt.Printf(err.Error())  return} fmt.Println(string(data)) Output: {"msg_name":"Alice"}更靈活地使用JSON使用json.RawMessagejson.RawMessage其實就是[]byte類型的重定義。
  • 如何使用Python 和 Pandas讀寫JSON文件
    在第一部分中,我們將使用Python包json來創建一個JSON文件並寫入一個JSON文件。在下一部分中,我們將使用Pandas的 json方法將JSON文件加載到Pandas 數據幀中。在這裡,我們將學習如何從本地和一個URL讀取JSON文件,以及如何使用Pandas讀取一個嵌套的JSON文件。
  • 使用golang解析yaml、json、xml文件
    = nil {  log.Fatal(err) } var data [7]Users err2 := yaml.Unmarshal(file, &data) if err2 !: chengdu  hobby:    - basketball    - guitar- name: 華子  age: 27  address: shenzhen  hobby:    - 王者榮耀- name: 喬克  age: 29  address: chongqing  hobby:
  • 使用 jsoncpp 手撕 json 讀寫
    有沒有好辦法,可以一次性解決 json 的讀寫問題?通常情況,我們在讀入 json 時,會將解析出來的數據寫入到結構體或類中。在生成 json 時,會將結構體或類中的數據寫入到 json 串中。因此,結構體成為了跟 json 的橋梁。能不能有通用的兩個模板函數,來實現對 json 讀寫。功能設計想實現 json 串和 結構體的相互轉換。
  • Go 語言網絡編程系列(九)— JSON 處理篇:JSON 編解碼基本使用入門
    /json 標準庫對 JSON 進行支持,開發者可以通過它輕鬆生成和解析 JSON 格式數據,下面我們來簡單演示下這個庫的使用。註:此函數功能可類比為 PHP 裡面的 json_encode 函數。通過如下形式對其進行初始化:user := User{ "學院君", "https://xueyuanjun.com", 18, true, []string{"Golang", "PHP", "C", "Java", "Python"},}然後,我們就可以使用
  • 簡要記錄丨VSCode 搭建基礎 C/C++ 編譯環境
    與tasks.json的label相對應24    }]25} 1{ 2    "files.defaultLanguage": "c++", // ctrl+N新建文件後默認的語言 3    "editor.formatOnType": true,  // 輸入分號(C/C++的語句結束標識)後自動格式化當前這一行的代碼 4
  • SQL Server 中 JSON_MODIFY 的使用
    SQL Server 中 JSON_MODIFY 的使用
  • mysql支持原生json使用說明
    ,本文將對MySQL中json類型的用法簡單說明,希望對你有用。", "vue"]');INSERT INTO `testproject` (student, skill) VALUES ('{"id": 5, "name": "guogege"}', '[]');插入json時,資料庫會對json做校驗,不符合json規範就會報錯。
  • 數據提取之JSON與JsonPATH
    Python 2.7及之後版本,自帶了JSON模塊,直接import json就可以使用了。官方文檔:http://docs.python.org/library/json.htmlJson在線解析網站:http://www.json.cn/#二、Json的基本使用