C++使用nlohmann json教程
使用指南:
1.include
#include
// for convenience
using json = nlohmann::json;
2.compile with(编译选项)
-std=c++11
3.makefile CMakeLists.txt
# CMakeLists.txt find_package(nlohmann_json 3.2.0 REQUIRED) ...
add_library(foo ...) ...
target_link_libraries(foo PRIVATE nlohmann_json::nlohmann_json)
使用方法:
json示例:
{
"pi": 3.141,
"happy": true,
"name": "Niels",
"nothing": null,
"answer": {
"everything": 42
},
"list": [1, 0, 2],
"object": {
"currency": "USD",
"value": 42.99
}
}
对应的代码如下:
// create an empty structure (null)
json j;
// add a number that is stored as double (note the implicit conversion of j to an object)
j["pi"] = 3.141;
// add a Boolean that is stored as bool
j["happy"] = true;
// add a string that is stored as std::string
j["name"] = "Niels";
// add another null object by passing nullptr
j["nothing"] = nullptr;
// add an object inside the object
j["answer"]["everything"] = 42;
// add an array that is stored as std::vector (using an initializer list)
j["list"] = { 1, 0, 2 };
// add another object (using an initializer list of pairs)
j["object"] = { {"currency", "USD"}, {"value", 42.99} };
//另一种代码写法:
// instead, you could also write (which looks very similar to the JSON above)
json j2 = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"answer", {
{"everything", 42}
}},
{"list", {1, 0, 2}},
{"object", {
{"currency", "USD"},
{"value", 42.99}
}}
};
序列化:
// 从字符串文本创建对象
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
// 比原始文本更好的方式
auto j2 = R"(
{
"happy": true,
"pi": 3.141
}
)"_json;
// 显示的解析
auto j3 = json::parse("{ \"happy\": true, \"pi\": 3.141 }");
// 显式的转换为字符串
std::string s = j.dump(); // {\"happy\":true,\"pi\":3.141}
// 打印显示序列化结果
// 将空格转换为缩进
std::cout << j.dump(4) << std::endl;
// {
// "happy": true,
// "pi": 3.141
// }
从文件读取/保存到文件:
// 读取JSON文件
std::ifstream i("file.json");
json j;
i >> j;
// 将json数据结构保存为文件
std::ofstream o("pretty.json");
o << std::setw(4) << j << std::endl;
类型转换:
namespace ns {
// 下面简单的结构介绍一个人
struct person {
std::string name;
std::string address;
int age;
};
}
一般的方法:
ns::person p = {"Ned Flanders", "744 Evergreen Terrace", 60};
// 转换为JSON:将每个值copy到JSON对象中。
json j;
j["name"] = p.name;
j["address"] = p.address;
j["age"] = p.age;
// ...
// 从JSON转换:从JSON对象中拷贝每个值。
ns::person p {
j["name"].get
j["address"].get
j["age"].get
};
更好的方法(nlohmann应用):
using nlohmann::json;
namespace ns {
void to_json(json& j, const person& p) {
j = json{ {"name", p.name}, {"address", p.address}, {"age", p.age}};
}
void from_json(const json& j, person& p) {
j.at("name").get_to(p.name);
j.at("address").get_to(p.address);
j.at("age").get_to(p.age);
}
} // namespace ns
// create a person
ns::person p {"Ned Flanders", "744 Evergreen Terrace", 60};
// conversion: person -> json
json j = p;
std::cout << j << std::endl;
// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
// conversion: json -> person
auto p2 = j.get
// that's it
assert(p == p2);
就这样!使用类型调用 json 构造函数时将自动调用自定义to_json方法。同样,当调用 get
如何转换第三方类型?
namespace nlohmann {
template
struct adl_serializer {
static void to_json(json& j, const T& value) {
// calls the "to_json" method in T's namespace
}
static void from_json(const json& j, T& value) {
// same thing, but with the "from_json" method
}
};
}
如何将 get() 用于非默认可构造/不可复制类型?
struct move_only_type {
move_only_type() = delete;
move_only_type(int ii): i(ii) {}
move_only_type(const move_only_type&) = delete;
move_only_type(move_only_type&&) = default;
int i;
};
namespace nlohmann {
template <>
struct adl_serializer
// 注意:返回类型不再是"void",该方法仅采用一个参数
static move_only_type from_json(const json& j) {
return {j.get
}
// 注意!你必须提供一个to_json方法!否则,您将无法将move_only_type转换为 json,
//因为您完全专有adl_serializer该类型。
static void to_json(json& j, move_only_type t) {
j = t.i;
}
};
}
例子:
#pragma once
#include
using json = nlohmann::json;
#include "sensor_data.h"
#include "rfid_info.h"
namespace nlohmann {
template <>
struct adl_serializer
// note: the return type is no longer 'void', and the method only takes
// one argument
static SensorData from_json(const json& j) {
SensorData sensor_data;
sensor_data.sensor_identify = j.at("SensorIdentify").get
return sensor_data;
}
// Here's the catch! You must provide a to_json method! Otherwise you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, SensorData t) {
j = json{ {"SensorIdentify",t.sensor_identify},{"SensorType",t.sensor_type },{"Data",t.data} };
}
};
template <>
struct adl_serializer
// note: the return type is no longer 'void', and the method only takes
// one argument
static RfidInfo from_json(const json& j) {
RfidInfo rfid_info;
rfid_info.identify = j.at("Identify").get
return rfid_info;
}
// Here's the catch! You must provide a to_json method! Otherwise you
// will not be able to convert move_only_type to json, since you fully
// specialized adl_serializer on that type
static void to_json(json& j, RfidInfo t) {
j = json{ { "Identify",t.identify },{ "Position",0 } };
}
};
}
二进制格式(BSON)
// create a JSON value
json j = R"({"compact": true, "schema": 0})"_json;
// serialize to BSON
std::vector
// 0x1B, 0x00, 0x00, 0x00, 0x08, 0x63, 0x6F, ...
// roundtrip
json j_from_bson = json::from_bson(v_bson);