C++ JSON庫nlohmann指南
nlohmann/json
nlohmann庫
nlohmann庫(https://github.com/nlohmann/json)提供了豐富而且符合直覺的接口(https://json.nlohmann.me/api/basic_json/),只需導(dǎo)入頭文件即可使用,方便整合到項(xiàng)目中。
聲明與構(gòu)造
可聲明普通json、數(shù)組或?qū)ο螅?/p>
using json = nlohmann::json; json j1; json j2 = json::object(); json j3 = json::array();
也可直接構(gòu)造(通過_json字面量,可以JSON格式直接構(gòu)造出):
json j = R"(
{
"name": "Mike",
"age": 15,
"score": 85.5
}
)"_json;
json j{
{ "name", "Mike"},
{ "age", 15 },
{ "score", 85.5}
};object生成
object可通過key-value方式賦值,或通過push_back添加:
// example for an object
json j_object = {{"one", 1},
{"two", 2}};
j_object["three"] = 3;
j_object.push_back({"four",4});
std::cout<<j_object<<std::endl;
for (auto &x : j_object.items()) {
std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
}
// {"four":4,"one":1,"three":3,"two":2}array生成
數(shù)組可通過json::array()或聲明初始化構(gòu)造;
json j_array = {1, 2, 4};
j_array.push_back(8);
j_array.emplace_back(16);
std::cout<<j_array<<std::endl;
// key為索引,從0開始
for (auto &x : j_array.items()) {
std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
}
// [1,2,4,8,16]
json j_aryObj = json::array();
j_aryObj.push_back({{"one", 1}});
j_aryObj.push_back({{"two", 2}});
std::cout<<j_aryObj<<std::endl;
for (auto &x : j_aryObj) {
std::cout << x << '\n';
}
// [{"one":1},{"two":2}]解析與序列化
從字符串中解析:
auto j = json::parse(str); // ... // 序列化為字符串 std::string out = j.dump();
從文件中解析:
json j;
std::ifstream("c:\\test.json") >> j;
// ...
// 序列化到文件
std::ofstream("c:\\test.json") << j;獲取與修改
可通過at或者operator[]的方式獲取元素的引用;然后通過get<T>()來獲取其值,直接賦值可修改其內(nèi)容:
- at返回對象的引用,當(dāng)不存在時(shí)會(huì)拋出異常(out_of_range或parse_error):
- at(key):根據(jù)下標(biāo)獲取數(shù)組元素;
- at(index):根據(jù)鍵獲取對象元素;
- at(jsonPtr):根據(jù)路徑獲取對象元素;
operator[]與at類似,不存在時(shí)可能會(huì)自動(dòng)添加null元素,而非拋出異常
void jsonAt() {
json j = {
{"number", 1},
{"string", "foo"},
{"array", {1, 2}}
};
std::cout << j << '\n';
std::cout << j.at("/number"_json_pointer) << '\n';
std::cout << j.at("/string"_json_pointer) << '\n';
std::cout << j.at("/array"_json_pointer) << '\n';
std::cout << j.at("/array/1"_json_pointer) << '\n';
auto ary = j.at("array");
std::cout<<ary.at(1)<<'\n';
auto n = j.at("number").get<int>();
auto str = j.at("string").get<std::string>();
std::cout<<n<<", "<<str<<'\n';
// change the string
j.at("/string"_json_pointer) = "bar";
// change an array element
j.at("/array/1"_json_pointer) = 21;
// output the changed array
std::cout << j["array"] << '\n';
// out_of_range.106
try {
// try to use an array index with leading '0'
json::reference ref = j.at("/array/01"_json_pointer);
}
catch (json::parse_error &e) {
std::cout << e.what() << '\n';
}
// out_of_range.109
try {
// try to use an array index that is not a number
json::reference ref = j.at("/array/one"_json_pointer);
}
catch (json::parse_error &e) {
std::cout << e.what() << '\n';
}
// out_of_range.401
try {
// try to use an invalid array index
json::reference ref = j.at("/array/4"_json_pointer);
}
catch (json::out_of_range &e) {
std::cout << e.what() << '\n';
}
// out_of_range.403
try {
// try to use a JSON pointer to a nonexistent object key
json::const_reference ref = j.at("/foo"_json_pointer);
}
catch (json::out_of_range &e) {
std::cout << e.what() << '\n';
}
}
// {"array":[1,2],"number":1,"string":"foo"}
// 1
// "foo"
// [1,2]
// 2
// 2
// 1, foo
// [1,21]
// [json.exception.parse_error.106] parse error: array index '01' must not begin with '0'
// [json.exception.parse_error.109] parse error: array index 'one' is not a number
// [json.exception.out_of_range.401] array index 4 is out of range
// [json.exception.out_of_range.403] key 'foo' not foundvalue
可通過value(key, defVal)來獲取元素,當(dāng)不存在時(shí)返回默認(rèn)值;但不能類型沖突(即,defValue的類型與key對應(yīng)元素的類型不匹配時(shí),會(huì)拋出type_error異常):
void jsonValue() {
json j = {
{"integer", 1},
{"floating", 42.23},
{"string", "hello world"},
{"boolean", true},
{"object", {{"key1", 1}, {"key2", 2}}},
{"array", {1, 2, 3}}
};
// access existing values
int v_integer = j.value("integer", 0);
double v_floating = j.value("floating", 0.0);
// access nonexisting values and rely on default value
std::string v_string = j.value("nonexisting", "[none]");
bool v_boolean = j.value("nonexisting", false);
// output values
std::cout << std::boolalpha << v_integer << " " << v_floating
<< " " << v_string << " " << v_boolean << "\n";
}
// 1 42.23 [none] false是否存在contains
通過contains可判斷元素是否存在:
- contains(key):根據(jù)鍵判斷;
- contains(jsonPtr):根據(jù)路徑判斷(對于數(shù)組,若索引不是數(shù)字會(huì)拋出異常);
查找find
查找指定的鍵(返回iterator):iterator find(key),通過*it獲取其值;
void jsonFind() {
// create a JSON object
json j_object = {{"one", 1},
{"two", 2}};
// call find
auto it_two = j_object.find("two");
auto it_three = j_object.find("three");
// print values
std::cout << std::boolalpha;
std::cout << "\"two\" was found: " << (it_two != j_object.end()) << '\n';
std::cout << "value at key \"two\": " << *it_two << '\n';
std::cout << "\"three\" was found: " << (it_three != j_object.end()) << '\n';
}刪除
通過erase可方便地刪除:
// {"rate":5000,"maxRate":8000,"name":"jon","more":{"count":5,"name":"mike"}}
string strJson = "{\"rate\":5000,\"maxRate\":8000,\"name\":\"jon\",\"more\":{\"count\":5,\"name\":\"mike\"}}";
auto jSet = nlohmann::json::parse(strJson);
auto ret = jSet.erase("rate");
ret = jSet.erase("name"); // ret=1
ret = jSet.erase("/more/count"); // 失敗,ret=0
auto result = jSet.dump(2);
std::cout << "result: " << result << std::endl;
// {"maxRate":8000,"more":{"count":5,"name":"mike"}}flatten
basic_json flatten()可扁平化所有鍵(全部展開成一層key-value,key為對應(yīng)的路徑),通過unflatten可反扁平化:
void jsonFlatten() {
// create JSON value
json j = {{"pi", 3.14},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"list", {1, 2, 3}},
{"object", {{"currency", "USD"}, {"value", 42.99}}}
};
// call flatten()
std::cout << j.dump(2) <<'\n';
std::cout << std::setw(4) << j.flatten() << '\n';
}
// {
// "happy": true,
// "list": [
// 1,
// 2,
// 3
// ],
// "name": "Niels",
// "nothing": null,
// "object": {
// "currency": "USD",
// "value": 42.99
// },
// "pi": 3.14
// }
// {
// "/happy": true,
// "/list/0": 1,
// "/list/1": 2,
// "/list/2": 3,
// "/name": "Niels",
// "/nothing": null,
// "/object/currency": "USD",
// "/object/value": 42.99,
// "/pi": 3.14
// }items
通過items可循環(huán)獲取所有元素:
void jsonItems(){
// create JSON values
json j_object = {{"one", 1}, {"two", 2}};
json j_array = {1, 2, 4, 8, 16};
// example for an object
for (auto& x : j_object.items())
{
std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
}
// example for an array
for (auto& x : j_array.items())
{
std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
}
}類型判斷
通過is_*判斷元素所屬類型:
- is_array:是數(shù)組
- is_object:是對象
- is_null:為空
- is_number:是數(shù)字(可繼續(xù)細(xì)化
is_number_float/is_number_integer/is_number_unsigned) - is_boolean:是布爾類型
- is_string:是字符串
- is_prmitive:是簡單類型(非數(shù)組與對象);
- is_strucctured:數(shù)組或?qū)ο螅?/li>
結(jié)構(gòu)體json
通過在結(jié)構(gòu)體所在的命名空間中創(chuàng)建void from_json(const json& j, MyStruct& p)可方便地從json中反序列化出結(jié)構(gòu)體;而通過void to_json(json &j, const MyStruct& p)可方便地把結(jié)構(gòu)體序列化為json;
通過get_to可把元素值賦值給類型兼容的變量:
namespace nj {
struct Asset {
std::string name;
int value;
};
void to_json(json &j, const Asset &a) {
j = json{{"name", a.name},
{"value", a.value}};
}
void from_json(const json &j, Asset &a) {
j.at("name").get_to(a.name);
j.at("value").get_to(a.value);
}
}示例
json構(gòu)造與操作的示例:
void jsonBuild() {
// {
// "pi": 3.141,
// "happy": true,
// "name": "Niels",
// "nothing": null,
// "answer": {
// "everything": 42
// },
// "list": [1, 0, 2],
// "object": {
// "currency": "USD",
// "value": 42.99
// }
//}
json jData;
jData["pi"] = 3.141;
jData["happy"] = true;
jData["name"] = "Niels";
jData["nothing"] = nullptr;
jData["answer"]["everything"] = 42; // 初始化answer對象
jData["list"] = {1, 0, 2}; // 使用列表初始化的方法對"list"數(shù)組初始化
jData["money"] = {{"currency", "USD"},
{"value", 42.99}}; // 初始化object對象
std::cout << std::boolalpha;
std::cout << jData << std::endl;
std::cout << jData.at("pi") << std::endl;
std::cout << jData["pi"].get<float>() << std::endl;
std::cout << jData["none"].is_null() << std::endl;
// std::cout << jData.at("notAt") << std::endl; // throw exception
std::cout << (jData.find("notFound") != jData.end()) << std::endl;
std::cout << jData.contains("notContain") << std::endl;
std::cout << jData.value("notExist", 0) << std::endl;
std::cout << "sub-object" << std::endl;
std::cout << jData.at("money") << std::endl;
std::cout << jData.contains("currency") << std::endl;
auto str = jData.dump(2);
std::cout << "JSON OUT: \n";
std::cout << str << std::endl;
// std::cout <<jData.value("name", 0)<<std::endl; // throw exception
}
// {"answer":{"everything":42},"happy":true,"list":[1,0,2],"money":{"currency":"USD","value":42.99},"name":"Niels","nothing":null,"pi":3.141}
// 3.141
// 3.141
// true
// false
// false
// 0
// sub-object
// {"currency":"USD","value":42.99}
// false
//
// JSON OUT:
// {
// "answer": {
// "everything": 42
// },
// "happy": true,
// "list": [
// 1,
// 0,
// 2
// ],
// "money": {
// "currency": "USD",
// "value": 42.99
// },
// "name": "Niels",
// "none": null,
// "nothing": null,
// "pi": 3.141
// }以上示例可看出:
- 通過
operator[]獲取不存在的key時(shí),會(huì)添加一個(gè)值為null的鍵值對; - 通過at獲取不存在的key時(shí),會(huì)拋出異常;
- 通過contains與find可判斷元素是否存在;
- 通過value獲取存在,但類型與默認(rèn)值不一致的元素時(shí),會(huì)拋出異常;
到此這篇關(guān)于C++ JSON庫nlohmann簡介的文章就介紹到這了,更多相關(guān)C++ JSON庫nlohmann內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++ vector容器 find erase的使用操作:查找并刪除指定元素
這篇文章主要介紹了C++ vector容器 find erase的使用操作:查找并刪除指定元素,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
C語言通過二分查找實(shí)現(xiàn)猜數(shù)字游戲
這篇文章主要為大家詳細(xì)介紹了在C語言中如何通過二分查找思想編寫一個(gè)簡單的猜數(shù)字游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-02-02

