nlohmann库(https://github.com/nlohmann/json)提供了丰富而且符合直觉的接口(https://json.nlohmann.me/api/basic_json/),只需导入头文件即可使用,方便整合到项目中。
可声明普通json、数组或对象:
json j1;
json j2 = json::object();
json j3 = json::array();
也可直接构造(通过_json
字面量,可以JSON格式直接构造出):
json j = R"(
{
"name": "Mike",
"age": 15,
"score": 85.5
}
)"_json;
json j{
{ "name", "Mike"},
{ "age", 15 },
{ "score", 85.5}
};
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<
数组可通过json::array()或声明初始化构造;
json j_array = {1, 2, 4};
j_array.push_back(8);
j_array.emplace_back(16);
std::cout<
从字符串中解析:
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
来获取其值,直接赋值可修改其内容:
operator[]
与at类似,不存在时可能会自动添加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<();
auto str = j.at("string").get();
std::cout<
可通过value(key, defVal)
来获取元素,当不存在时返回默认值;但不能类型冲突(即,defValue的类型与key对应元素的类型不匹配时,会抛出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可判断元素是否存在:
查找指定的键(返回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';
}
basic_json flatten()
可扁平化所有键(全部展开成一层key-value,key为对应的路径),通过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可循环获取所有元素:
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_number_float/is_number_integer/is_number_unsigned
)通过在结构体所在的命名空间中创建void from_json(const json& j, MyStruct& p)
可方便地从json中反序列化出结构体;而通过void to_json(json &j, const MyStruct& p)
可方便地把结构体序列化为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构造与操作的示例:
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"数组初始化
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() << 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 <
以上示例可看出:
operator[]
获取不存在的key时,会添加一个值为null的键值对;