相关链接
GitHub:https://github.com/nlohmann/json
api文档:https://nlohmann.github.io/json/api/basic_json/
头文件添加
// json.hpp 唯一需要引入的文件
#include
// 使用如下语句方便使用
using json = nlohmann::json;
CMakeLists 添加
find_package(nlohmann_json 3.2.0 REQUIRED) # 找包
target_link_libraries(${PROJECT_NAME}
PRIVATE
nlohmann_json::nlohmann_json) # link 库
示例 | 说明 |
---|---|
简单使用 | json对象的创建 |
序列化与反序列化 | 1、字符串的序列化与反序列化 2、流的序列化与反序列化(输入输出流+文件流) |
像STL一样操作json对象 | json对象形如STL操作的方法使用 |
Json Pointer 与 Patch | 1、_json_pointer 的使用 2、patch与merge_patch的补丁操作 |
解析简单json文件 | 读取简单json文件,并将数据存放到不容变量中 |
解析json文件为结构体以及将结构存放为json文件 | 1、读取json文件多级数据并存放为结构体,int 、string、数组 2、将结构体数据循环处理后存放入json文件 |
demo: SimpleUseTest
GitHub SimpleUseTest
#include
// json.hpp 唯一需要引入的文件
#include
// 使用如下语句方便使用
using json = nlohmann::json;
int main() {
/// 简单使用
//创建一个空的结构
json j1;
// 数字 存储为 double
j1["pi"] = 3.141;
// Boolean 存储为 bool
j1["happy"] = true;
// 字符串 存储为 std::string
j1["name"] = "Niels";
// 空值 传入 nullptr
j1["nothing"] = nullptr;
// 直接加入其他对象
j1["answer"]["everything"] = 42;
// 加入一个 array 存储为 std::vector (使用初始化列表)
j1["list"] = { 1, 0, 2 };
// 添加其他对象 (使用键值对初始化列表)
j1["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}
}}
};
std::cout << "json j1 = " << j1 << std::endl;
std::cout << "json j2 = " << j2 << std::endl;
///可使用函数 json::array() 和 json::object() 等 显示表示
// 空数组
json empty_array_explicit = json::array();
// 空 {} 对象
json empty_object_implicit = json({});
json empty_object_explicit = json::object();
// 通过 key/value 键值对创建数组 [["currency", "USD"], ["value", 42.99]]
json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
std::cout << "json empty_array_explicit = " << empty_array_explicit << std::endl;
std::cout << "json empty_object_implicit = " << empty_object_implicit << std::endl;
std::cout << "json empty_object_explicit = " << empty_object_explicit << std::endl;
std::cout << "json array_not_object = " << array_not_object << std::endl;
std::cout << "json array_not_object[?][?] = " << array_not_object[1] << std::endl;
return 0;
}
json j1 = {"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}
json j2 = {"answer":{"everything":42},"happy":true,"list":[1,0,2],"name":"Niels","nothing":null,"object":{"currency":"USD","value":42.99},"pi":3.141}
json empty_array_explicit = []
json empty_object_implicit = {}
json empty_object_explicit = {}
json array_not_object = [["currency","USD"],["value",42.99]]
json array_not_object[?][?] = ["value",42.99]
Process finished with exit code 0
demo:SerializationAndDeserialization
GitHub SerializationAndDeserialization
#include
#include
#include
#include
using json = nlohmann::json;
int main() {
/// 字符串 序列化与反序列化
// 通过添加 _json 后缀将字符串反序列化为json变量
json j1 = "{ \"happy\": true, \"pi\": 3.141 }"_json;
// 最好使用原始字符串
auto j2 = R"({"happy": true,"pi": 3.141})"_json;
// 使用 json::parse() 显示使用
auto j3 = json::parse(R"({ "happy": true, "pi": 3.141 })");
std::cout << "json j1" << j1 << std::endl;
std::cout << "json j2" << j2 << std::endl;
std::cout << "json j3" << j3 << std::endl;
// 将json变量序列化为 字符串 .dump()返回最初存储的字符串值。 dump() dump(4) 4 显示格式便于查看
std::string s = j3.dump(); // {"happy":true,"pi":3.141}
std::cout << "string s j3.dump()" << s << std::endl;
std::cout << "string s j3.dump(4)" << j3.dump(4) << std::endl;
/// 序列化和赋值之间的区别
/// 库只支持UTF-8 存储具有不同编码的字符串时,调用dump()可能会引发异常
// 将字符串存储在JSON值中
json j_string = "this is a string";
std::cout << "json j_string = " << j_string << std::endl;
// 获取字符串值 j_string.get()
auto cpp_string = j_string.get<std::string>();
std::cout << "j_string.get() cpp_string = " << cpp_string << std::endl;
// 获取字符串值 并存到 变量
std::string cpp_string2;
j_string.get_to(cpp_string2);
// 获取序列化的值(显式JSON序列化)
std::string serialized_string = j_string.dump();
// 输出原始字符串
std::cout << "original string: " << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
// 出书序列化值
std::cout << "serialized value: " << j_string << " == " << serialized_string << std::endl;
/// 从标准输入输出流中 序列化与反序列化
// 从标准输入反序列化
json j4;
std::cout << "please input:" << std::endl;
std::cin >> j4;
// 序列化到标准输出
std::cout << j4 << std::endl;
// 格式化输出
std::cout << std::setw(4) << j4 << std::endl;
/// 从文件流中 序列化与反序列化
// 读取一个json文件
std::ifstream i("file.json");
json j5;
i >> j5;
std::cout << "json j5 = " << j5 << std::endl;
// 将美化的JSON写入另一个文件
std::ofstream o("pretty.json");
o << std::setw(4) << j5 << std::endl; // std::setw(4) 设置格式
return 0;
}
json j1{"happy":true,"pi":3.141}
json j2{"happy":true,"pi":3.141}
json j3{"happy":true,"pi":3.141}
string s j3.dump(){"happy":true,"pi":3.141}
string s j3.dump(4){
"happy": true,
"pi": 3.141
}
json j_string = "this is a string"
j_string.get() cpp_string = this is a string
original string: this is a string == this is a string == this is a string
serialized value: "this is a string" == "this is a string"
please input:
{"happy":true,"pi":3.141}
{"happy":true,"pi":3.141}
{
"happy": true,
"pi": 3.141
}
json j5 = {"output":{"crf":31,"frameRate":20,"height":1080,"width":1000},"tracks":[{"name":"t1","pieces":[{"endTime":6,"file":"x.mp4","startTime":2},{"endTime":13,"file":"y.mp4","startTime":9}]},{"name":"t2","pieces":[{"endTime":10,"file":"z.mp4","startTime":0}]}]}
Process finished with exit code 0
demo:Access_STL_like
GitHub Access_STL_like
#include
// json.hpp 唯一需要引入的文件
#include
// 使用如下语句方便使用
using json = nlohmann::json;
// 函数可参看 api : https://nlohmann.github.io/json/api/basic_json/
int main() {
// 使用 push_back 创建数组, 将给定元素Val附加到JSON数组的末尾
json j;
j.push_back("foo");
j.push_back(1);
j.push_back(true);
std::cout << "json j = " << j << std::endl;
// emplace_back 在j尾部 加入 根据传递的参数arg创建的JSON值
j.emplace_back(1.78);
std::cout << "json j = " << j << std::endl;
// 迭代器遍历
for (json::iterator it = j.begin(); it != j.end(); ++it) {
std::cout << *it << '\n';
}
std::cout << "==============" << std::endl;
// 遍历 j
for (auto& element : j) {
std::cout << element << '\n';
}
std::cout << "==============" << std::endl;
// 取值 设置值
const auto tmp = j[0].get<std::string>();
std::cout << "json j = " << j << std::endl;
j[1] = 42;
std::cout << "json j = " << j << std::endl;
bool foo = j.at(2);
std::cout << " j.at(2) = " << foo << std::endl;
std::cout << "==============" << std::endl;
// 是否相等
std::cout <<"j == \"[\\\"foo\\\", 42, true]\"_json : " << (j == "[\"foo\", 42, true]"_json) << std::endl;
// size
std::cout << "j.size() : " << j.size() << std::endl;
// 是否为空
std::cout << "j.empty() : " << j.empty() << std::endl;
// 类型
j.type(); // 返回类型
auto name = j.type_name(); // 将类型名称作为字符串返回
std::cout << "j.type() : " << name << std::endl;
// 清空
j.clear();
std::cout << "json j = " << j << std::endl;
std::cout << "==============" << std::endl;
// 方便的类型检查
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;
// 也可以通过 emplace 添加新元素
o.emplace("weather", "sunny");
std::cout << "json o = " << o << std::endl;
// 迭代器遍历
for (json::iterator it = o.begin(); it != o.end(); ++it) {
std::cout << it.key() << " : " << it.value() << "\n";
}
std::cout << "==============" << std::endl;
for (auto& el : o.items()) {
std::cout << el.key() << " : " << el.value() << "\n";
}
std::cout << "==============" << std::endl;
// 结构化绑定 (C++17)
for (auto& [key, value] : o.items()) {
std::cout << key << " : " << value << "\n";
}
std::cout << "==============" << std::endl;
// contains 查找是否包含 key 值
if (o.contains("foo")) {
std::cout << R"(o.contains("foo"))" << std::endl;
}
// 通过 find
if (o.find("foo") != o.end()) {
std::cout << R"(o.find("foo"))" << std::endl;
}
// 通过 count 返回 key 的个数
int foo_present = o.count("foo"); // 1
int fob_present = o.count("fob"); // 0
// 删除 某个键值对
o.erase("foo");
std::cout << "json o = " << o << std::endl;
return 0;
}
json j = ["foo",1,true]
json j = ["foo",1,true,1.78]
"foo"
1
true
1.78
==============
"foo"
1
true
1.78
==============
json j = ["foo",1,true,1.78]
json j = ["foo",42,true,1.78]
j.at(2) = 1
==============
j == "[\"foo\", 42, true]"_json : 0
j.size() : 4
j.empty() : 0
j.type() : array
json j = []
==============
json o = {"bar":false,"baz":3.141,"foo":23,"weather":"sunny"}
bar : false
baz : 3.141
foo : 23
weather : "sunny"
==============
bar : false
baz : 3.141
foo : 23
weather : "sunny"
==============
bar : false
baz : 3.141
foo : 23
weather : "sunny"
==============
o.contains("foo")
o.find("foo")
json o = {"bar":false,"baz":3.141,"weather":"sunny"}
Process finished with exit code 0
demo: JsonPointerAndPatch
GitHub JsonPointerAndPatch
#include
// json.hpp 唯一需要引入的文件
#include
// 使用如下语句方便使用
using json = nlohmann::json;
int main() {
/// _json_pointer
json j_original = R"({
"baz": ["one", "two", "three"],
"foo": "bar"
})"_json;
std::cout << "json j_original = " << j_original << std::endl;
// 通过json指针访问成员
// 如果没有 会新增元素其值为null
// eg: j_original["/baz/5"_json_pointer] 会在 增加元素 到 6 个
auto var1 = j_original["/baz/1"_json_pointer]; // "two"
auto var2 = j_original["/baz/2"_json_pointer]; // "three"
auto var5 = j_original["/baz/5"_json_pointer]; // null
std::cout << "var1 = " << var1 << std::endl;
std::cout << "var2 = " << var2 << std::endl;
std::cout << "var3= " << j_original["/baz/3"_json_pointer] << std::endl;
std::cout << "var4 = " << j_original["/baz/4"_json_pointer] << std::endl;
std::cout << "var5 = " << var5 << std::endl;
std::cout << "=============" << std::endl;
/// patch
// 补丁操作
// "op": 指定操作 "path":指定 key值 "value":指定值
json j_patch = R"([
{ "op": "replace", "path": "/baz", "value": "boo" },
{ "op": "add", "path": "/hello", "value": ["world"] },
{ "op": "remove", "path": "/foo"}
])"_json;
// 运行补丁, 不会修改原数据,返回修改后的数据
json j_result = j_original.patch(j_patch);
std::cout << "json j_original = " << j_original << std::endl;
std::cout << "json j_result = " << j_result << std::endl;
// {
// "baz": "boo",
// "hello": ["world"]
// }
// 创建一个JSON Patch,以便通过调用修补程序函数将 源值(j_original) 更改为 目标值(j_result)
// 故 source.patch(diff(source, target)) == target; 总是为 true
auto op_patch = json::diff(j_result, j_original);
std::cout << "op_patch = " << op_patch << std::endl;
// [
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
// { "op": "remove","path": "/hello" },
// { "op": "add", "path": "/foo", "value": "bar" }
// ]
std::cout << "=============" << std::endl;
/// Merge Patch
// 可以不是用_json_pointer而是使用 merge_patch 来修改元素
// 根据 j_patch 的值,操作 原数据
json j_document = R"({
"a": "b",
"c": {
"d": "e",
"f": "g"
}
})"_json;
std::cout << "json j_document = " << j_document << std::endl;
// a patch
json j_patch2 = R"({
"a":"z",
"c": {
"f": null
}
})"_json;
std::cout << "json j_patch2 = " << j_patch2 << std::endl;
j_document.merge_patch(j_patch);
std::cout << "json j_document = " << j_document << std::endl;
// {
// "a": "z",
// "c": {
// "d": "e"
// }
// }
std::cout << "=============" << std::endl;
return 0;
}
json j_original = {"baz":["one","two","three"],"foo":"bar"}
var1 = "two"
var2 = "three"
var3= null
var4 = null
var5 = null
=============
json j_original = {"baz":["one","two","three",null,null,null],"foo":"bar"}
json j_result = {"baz":"boo","hello":["world"]}
op_patch = [{"op":"replace","path":"/baz","value":["one","two","three",null,null,null]},{"op":"remove","path":"/hello"},{"op":"add","path":"/foo","value":"bar"}]
=============
json j_document = {"a":"b","c":{"d":"e","f":"g"}}
json j_patch2 = {"a":"z","c":{"f":null}}
json j_document = [{"op":"replace","path":"/baz","value":"boo"},{"op":"add","path":"/hello","value":["world"]},{"op":"remove","path":"/foo"}]
=============
Process finished with exit code 0
demo: ParseJsonFileSimple
GitHub ParseJsonFileSimple
#include
#include
#include
using json = nlohmann::json;
/**
simple.json 文件
{
"ok":true,
"height": 20.123,
"width": 1000,
"name": "test"
}
*/
int main() {
json j; // json 对象
std::ifstream jfile("simple.json"); // 流读取
jfile >> j; // 文件流形式读取 json 文件, 并存为 j
jfile.close();
std::cout << "json j = " << j << std::endl;
bool ok = j.at("ok");
float height = j["height"];
int width = j["width"];
std::string name = j.at("name");
std::cout << "ok = " << ok << std::endl;
std::cout << "height = " << height << std::endl;
std::cout << "width = " << width << std::endl;
std::cout << "name = " << name << std::endl;
return 0;
}
json j = {"height":20.123,"name":"test","ok":true,"width":1000}
ok = 1
height = 20.123
width = 1000
name = test
Process finished with exit code 0
demo:ParseJsonFileComplex
GitHub ParseJsonFileComplex
#include
// json.hpp 唯一需要引入的文件
#include
#include
#include
// 使用如下语句方便使用
using json = nlohmann::json;
/*
Complex.json 文件
{
"output": {
"width": 720,
"height": 1080,
"frameRate": 20,
"crf": 31
},
"tracks": [
{
"name": "t1",
"pieces": [
{
"file": "x.mp4",
"startTime": 2,
"endTime": 6
},
{
"file": "y.mp4",
"startTime": 9,
"endTime": 13
}
]
},
{
"name": "t2",
"pieces": [
{
"file": "z.mp4",
"startTime": 0,
"endTime": 10
}
]
}
]
}
*/
///从这个 json 文件,可以看到,它包括两大部分 "output" 和 "tracks"。
/// "tracks" 为数组有两个元素,包括 string 的 name,和另一个结构体 "pieces" 的数组。
/// 可以定义 3个结构体 outputinfo pieceinfo trackinfo
namespace jsonns {
struct outputinfo {
int width;
int height;
int frameRate;
int crf;
};
struct pieceinfo {
std::string pathname;
int startTime{};
int endTime{};
};
struct trackinfo {
std::string name;
pieceinfo pieces[5];
int size{};
};
/// j: json文件中 output 部分 , v: 结构体 outputinfo
void from_json(const json& j, outputinfo& v) {
j.at("width").get_to(v.width);
j.at("height").get_to(v.height);
j.at("frameRate").get_to(v.frameRate);
j.at("crf").get_to(v.crf);
}
/// j: json文件中 pieces 部分 , v: 结构体 pieceinfo
void from_json(const json&j, pieceinfo &p) {
j.at("file").get_to(p.pathname);
j.at("startTime").get_to(p.startTime);
j.at("endTime").get_to(p.endTime);
}
/// j: json文件中 tracks 部分 , v: 结构体 trackinfo
void from_json(const json&j, trackinfo &t) {
j.at("name").get_to(t.name);
/// 遍历 tracks 中 多个 pieces
int len = j["pieces"].size();
for(int i = 0; i < len; i++) {
t.pieces[i] = j["pieces"][i];
}
t.size = j["pieces"].size();
}
}
/**
* 1、从 json文件读取数据并存为结构体
* 2、将结构体按json格式存到文件
* @return
*/
int main() {
std::cout << "Hello, World!" << std::endl;
/****** 从json文件中读取数据 并 存放为结构体******/
json j;
std::ifstream jfile("Complex.json");
jfile >> j;
jfile.close();
std::cout << "json j = " << j << std::endl;
jsonns::outputinfo vi = j.at("output");
/// tilength json文件中key = "tracks"值的大小
int tilength = j["tracks"].size();
/// 创建 trackinfo 数组
jsonns::trackinfo ti[tilength];
/// 填充数据
for (int i = 0; i < tilength; i++) {
ti[i] = j["tracks"][i];
}
/****** 从json文件中读取数据 并 存放为结构体 end******/
/******* 将结构体数据存成json对象 并 写入文件 ******/
json j2;
// "output" 数据
j2["output"]["width"] = vi.width;
j2["output"]["height"] = vi.height;
j2["output"]["frameRate"] = vi.frameRate;
j2["output"]["crf"] = vi.crf;
// "tracks" 数据, 是个数组
json tracks;
for (int i = 0; i < tilength; i++) {
json ttmp;
ttmp["name"] = ti[i].name;
int len = ti[i].size; // pieces 多少个
// "pieces" 数据 是个数组
json pieces;
for (int k = 0; k < len; ++k) {
json ptmp;
ptmp["file"] = ti[i].pieces[k].pathname;
ptmp["startTime"] = ti[i].pieces[k].startTime;
ptmp["endTime"] = ti[i].pieces[k].endTime;
pieces.push_back(ptmp); // 是 数组 通过 push_back 添加
}
ttmp["pieces"] = pieces;
tracks.push_back(ttmp); // 是 数组 通过 push_back 添加
}
j2["tracks"] = tracks;
std::cout << "json j2 = " << j2 << std::endl;
std::ofstream o("pretty.json");
o << std::setw(4) << j2 << std::endl; // std::setw(4) 设置格式
o.close();
/******* 将结构体数据存成json对象 并 写入文件 end******/
return 0;
}
Hello, World!
json j = {"output":{"crf":31,"frameRate":20,"height":1080,"width":720},"tracks":[{"name":"t1","pieces":[{"endTime":6,"file":"x.mp4","startTime":2},{"endTime":13,"file":"y.mp4","startTime":9}]},{"name":"t2","pieces":[{"endTime":10,"file":"z.mp4","startTime":0}]}]}
json j2 = {"output":{"crf":31,"frameRate":20,"height":1080,"width":720},"tracks":[{"name":"t1","pieces":[{"endTime":6,"file":"x.mp4","startTime":2},{"endTime":13,"file":"y.mp4","startTime":9}]},{"name":"t2","pieces":[{"endTime":10,"file":"z.mp4","startTime":0}]}]}
Process finished with exit code 0
#include
// json.hpp 唯一需要引入的文件
#include
#include
#include
// 使用如下语句方便使用
using json = nlohmann::json;
namespace jsonns {
struct outputinfo {
int width;
int height;
int frameRate;
int crf;
};
struct pieceinfo {
std::string pathname;
int startTime{};
int endTime{};
};
struct trackinfo {
std::string name;
pieceinfo pieces[5];
int size{};
};
/// j: json文件中 output 部分 , v: 结构体 outputinfo
void from_json(const json &j, outputinfo &v) {
j.at("width").get_to(v.width);
j.at("height").get_to(v.height);
j.at("frameRate").get_to(v.frameRate);
j.at("crf").get_to(v.crf);
}
/// j: json文件中 pieces 部分 , v: 结构体 pieceinfo
void from_json(const json &j, pieceinfo &p) {
j.at("file").get_to(p.pathname);
j.at("startTime").get_to(p.startTime);
j.at("endTime").get_to(p.endTime);
}
/// j: json文件中 tracks 部分 , v: 结构体 trackinfo
void from_json(const json &j, trackinfo &t) {
j.at("name").get_to(t.name);
/// 遍历 tracks 中 多个 pieces
int len = j["pieces"].size();
for(int i = 0; i < len; i++) {
///t.pieces[i] = j["pieces"][i];
from_json(j["pieces"][i],t.pieces[i] );
}
t.size = j["pieces"].size();
}
/// j: json文件中 output 部分 , v: 结构体 outputinfo
void to_json(const outputinfo &v, json &j) {
j["width"] = v.width;
j["height"] = v.height;
j["frameRate"] = v.frameRate;
j["crf"] = v.crf;
}
void to_json(const pieceinfo &p ,json &j) {
j["file"] = p.pathname;
j["startTime"] = p.startTime;
j["endTime"] = p.endTime;
}
/// j: json文件中 tracks 部分 , v: 结构体 trackinfo
void to_json(const trackinfo &t,json &j) {
j["name"] = t.name;
/// 遍历 tracks 中 多个 pieces
int len = t.size;
for(int i = 0; i < len; i++) {
to_json(t.pieces[i],j["pieces"][i]);
}
}
}
/**
* 1、从 json文件读取为结构体
* 2、将结构体按json格式存到文件
* @return
*/
int main() {
std::cout << "Hello, World!" << std::endl;
/****** 从json文件中读取数据 并 存放为结构体******/
json j;
std::fstream jfile;
jfile.open("Complex.json");
jfile >> j;
jfile.close();
std::cout << "json j = " << j << std::endl;
///jsonns::outputinfo vi = j.at("output");
jsonns::outputinfo vi{};
jsonns::from_json(j.at("output"),vi);
/// tilength json文件中key = "tracks"值的大小
int tilength = j["tracks"].size();
/// 创建 trackinfo 数组
jsonns::trackinfo ti[tilength];
/// 填充数据
for (int i = 0; i < tilength; i++) {
//ti[i] = j["tracks"][i];
jsonns::from_json(j["tracks"][i],ti[i]);
}
/****** 从json文件中读取数据 并 存放为结构体 end******/
/******* 将结构体数据存成json对象 并 写入文件 ******/
json j2;
// "output" 数据
jsonns::to_json(vi,j2["output"]);
int tiSize = ti->size;
for (int i = 0; i < tiSize; i++) {
to_json(ti[i],j2["tracks"][i]);
}
std::cout << "json j2 = " << j2 << std::endl;
std::ofstream o("pretty.json");
o << std::setw(4) << j2 << std::endl; // std::setw(4) 设置格式
o.close();
/******* 将结构体数据存成json对象 并 写入文件 end******/
return 0;
}
如果您只想序列化/反序列化某些结构,则to_json / from_json函数可能是很多样板,可以利用两个宏来简化你的编码。
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(name, member1, member2, ...)
将在要为其创建代码的类/结构的命名空间内定义。
NLOHMANN_DEFINE_TYPE_INTRUSIVE(name, member1, member2, ...)
将在要为其创建代码的类/结构中定义。 该宏还可以访问私有成员。
两个宏定义如下,其用到了可变参数宏的展开,宏重载相关内容,参见不定参数宏展开与__VA_ARGS__
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
/*!
@brief macro
@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
@since version 3.9.0
*/
#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
#include
#include
#include "json.hpp"
using json = nlohmann::json;
class Address {
public:
Address(){
postcode = 1024;
housenumber = 100;
street = "this is a address";
}
~Address() = default;
int postcode;
public:
void show(){
std::cout << "postcode = " << postcode << std::endl;
std::cout << "housenumber = " << housenumber << std::endl;
std::cout << "street = " << street << std::endl;
}
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Address, street, housenumber, postcode)
//NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Address, street, housenumber, postcode) // 存在 private 不能使用 这个宏
private:
std::string street;
int housenumber;
};
namespace ns {
struct Student {
int age{};
int num{};
std::string name;
};
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Student, age, num, name)
}
int main() {
Address add1;
add1.postcode = 4096;
json j1 = add1;
std::cout << std::setw(4) << j1 <<std::endl;
Address add2;
add2 = j1;
add2.show();
ns::Student st1;
st1.name = "张三";
st1.num = 1;
st1.age = 18;
json j2 = st1;
std::cout << std::setw(4) << j2 <<std::endl;
ns::Student st2;
st2 = j2;
std::cout << "st2.name = " << st2.name << std::endl;
std::cout << "st2.num = " << st2.num << std::endl;
std::cout << "st2.age = " << st2.age << std::endl;
return 0;
}
{
"housenumber": 100,
"postcode": 4096,
"street": "this is a address"
}
postcode = 4096
housenumber = 100
street = this is a address
{
"age": 18,
"name": "张三",
"num": 1
}
st2.name = 张三
st2.num = 1
st2.age = 18
Process finished with exit code 0
希望我的文章对于大家有帮助,由于个人能力的局限性,文中可能存在一些问题,欢迎指正、补充!