当我们有很多参数需要读入程序时,可以将这些参数写在一个input文件中,程序启动后读入。如果输入的参数还具有一定的层级关系而变得复杂时,那就可以考虑使用json格式的输入文件了。例如下面这样的输入:
{
"pi": 3.141,
"happy": true,
"name": "Niels",
"nothing": null,
"answer": {
"everything": 42
},
"list": [1, 0, 2],
"object": {
"currency": "USD",
"value": 42.99
}
}
本文推荐一个非常好用的json文件读写开源库,并介绍一些满足大多数人使用场景的基础用法。
开源库:nlohmann/json,地址:https://github.com/nlohmann/json
安装安装方式非常简单,将库中的nlohmann文件夹拷贝到/usr/include中即可(linux操作系统)。
使用在主函数文件中引用头文件:
#include "nlohmann/json.hpp" using json = nlohmann::json;
在讲怎样从文件中读取json数据之前,先说说开源库中定义的json对象。
-
定义json对象
// 定义json对象,像初始化c++map类型对象一样初始化json对象 json j; j["pi"] = 3.14; j["name"] = "Niels"; j["if_happy"] = true; j["nothing"] = nullptr; j["book"]["id"] = 12345; j["book"]["price"] = 12.5; j["list"] = {1,0,3}; j["object"] = {{"currency","usd"},{"value",22.5}};此时json对象j已经含有上述初始化的各个成员,成员的获取如下:
// 成员获取示例1 double num_pi; num_pi = j["pi"].get
(); // 成员获取示例2 auto money = j["object"]; cout< -
c++ string对象与json对象的数据交换
// 使用string对象解析获得json对象,用到json::parse(string s)函数 string s; // 从json对象获得对象的内容并放入string对象中(术语叫序列化),数字4指的是对象输出的字符串换行的缩进为4 s = j.dump(4); cout<
-
json对象的文件读入与输出
// 终于到了文件了,这部分是大部分人需要用到的,就是从文件中读入json,或者输出json格式的文件 ofstream os{"out.plt"}; if(!os) cout<<"file open failed"<"out.plt"}; if(!is) cout<<"input file open failed"< >j; cout< -
枚举变量在json对象中怎么表示
由于默认情况下json把枚举序列化为整型,可能会出现错误,所以需要使用宏定义NLOHMANN_JSON_SERIALIZE_ENUM来把枚举变量和string绑定在一起,且定义一个无效的枚举变量来防止错误,枚举这块比较绕,可以参考链接:https://json.nlohmann.me/features/enum_conversion/// example enum type declaration enum class TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED, TS_INVALID=-1, }; // map TaskState values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { {TaskState::TS_INVALID, nullptr}, {TaskState::TS_STOPPED, "stopped"}, {TaskState::TS_RUNNING, "running"}, {TaskState::TS_COMPLETED, "completed"}, }) s = R"({ "task":"running" })"; // json key:value对的value现在用宏定义绑定的string来赋值,json对象自动会将其匹配到对应的枚举变量 j = json::parse(s); TaskState task=j["task"]; cout<(task)< -
用户自定义类对象与json对象的数据互传
如果用户自定义的类对象需要从json对象读入成员变量的值,或者从对象中抽出数据到json对象中,可以定义两个名为to_json()和from_json()的函数,即可直接使用 = 赋值运算符来操作json对象和用户自定义对象的互相转换了
class person{ public: string name; int age; }; person p{"Taylor",18}; j = p; cout<上面这个方法已经够简单了,但是Lohmann还提供了更方便的宏定义,只需使用
LOHMANN_DEFINE_TYPE_NON_INTRUSIVE(类名字,依次写出和json对象共有的成员变量)即可,不用写出to_json()和from_json()。具体本文最后给出的示例参考文件开头部分的宏定义:NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, age);
全部代码如下:
#include#include #include #include #include "nlohmann/json.hpp" using json=nlohmann::json; using namespace std; class person{ public: string name; int age; }; // 方式1 , 如果使用该方式,将下面 #if 0 改为 #if 1 #if 0 void to_json(json& j, const person& p) { j = json{{"name", p.name}, {"age",p.age}}; } void from_json(const json& j, person& p) { p = person{j["name"].get (), j["age"].get ()}; } #else // 方式2 NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(person, name, age); #endif // example enum type declaration enum class TaskState { TS_STOPPED, TS_RUNNING, TS_COMPLETED, TS_INVALID=-1, }; // map TaskState values to JSON as strings NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, { {TaskState::TS_INVALID, nullptr}, {TaskState::TS_STOPPED, "stopped"}, {TaskState::TS_RUNNING, "running"}, {TaskState::TS_COMPLETED, "completed"}, }) int main() { cout<<"--------------------- part 1 -------------------"< 1,0,3}; j["object"] = {{"currency","usd"},{"value",22.5}}; cout< (); // 成员获取示例2 auto money = j["object"]; cout< "out.plt"}; if(!os) cout<<"file open failed"< "out.plt"}; if(!is) cout<<"input file open failed"< >j; cout< "Taylor",18}; j = p; cout< (task)< 靓仔,你学费了吗?有问题评论区见~
参考:
https://blog.csdn.net/u011341856/article/details/108797920
https://json.nlohmann.me/features/enum_conversion/



