C++使⽤nlohmann解析Json数据数据对象建模援引百度百科:json是⼀种轻量级的数据交换格式。对于习惯了python语⾔的我来说,json可以和内置的dict(字典)数据类型完美
衔接, 所以就想着能不能横向推⼴到C++。 在GitHub上⼀搜索,发现star最⾼的nlohmann;主要的⽤法⼯程的readme其实已经说的很清楚了。
但是翻了很多博客,发现对于json 对象建模以及其相互转换的⽂档不多。此篇⽂章主要介绍读取json⽂件以及对象建模。希望对⼤家有所帮助!
⼀:将nlohmann库添加到⾃⼰的⼯程
使⽤nlohmann,我们只需将json.hpp头⽂件添加到⾃⼰的代码中(这个超级Nice)
#include <json.hpp>
// 为了使⽤⽅便,可以让json命名空间内所有标识符在此⽂件中可见
using json = nlohmann::json;
⼆:简单json字符串序列化/反序列化
1. 反序列化成json
现有json字符串格式如下
{
"pi":3.1415,
"happy":true
}
将其反序列化成json对象
//⽅式1:在序列化后字符串后后添加 _json后缀
json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
//⽅式2:从原⽣字符串
auto j2 = R"(
{
"happy": true,
"pi": 3.141
}
)"_json;
//⽅式3:显⽰的调⽤ json::parse
auto j3 = json::parse(R"({"happy": true, "pi": 3.141})");
//⽅式4:从json⽂件中读取
std::ifstream ifs("test.json");
json jf = json::parse(ifs);
2. 序列化成json格式字符串
/
/ 显⽰的转换
std::string s = j.dump(); // {"happy":true,"pi":3.141}
3. 读取json⽂件
std::ifstream ifs("test.json");
json jf = json::parse(ifs);
4. 保存成json⽂件
jsonf jsonfile;
jsonfile["happy"]= true;
jsonfile["pi"]=3.141;
std::ofstream file("test.json");
file << jsonfile;
三:较复杂的嵌套json字符串数据对象建模现有json字符串格式如下:
{
"teacher_name":"wangwu",
"student_list":
[
{
"name":"zhangsan",
"age":16,
"phone":"12345678"
},
{
"name":"lisi",
"age":17,
"phone":"123456"
}
]
}
对于较为复杂的嵌套json字符串,通⽤的做法是对其进⾏建模,对应到C++则是结构体/类
1. json字符串分析
直观的看的话, 此json字符串包含两种两⼤部分:teacher_name和student_list, 其中student_list是⼀个数组。student_list嵌套的内容包含name、age和phone3个字段
2. 建模
1. 最⾥层的表⽰学⽣对象的json字符串可转成对应的 student 类/结构体
class student
{
public:
string name;
int age;
string phone;
};
2. 外层的表⽰班主任及学⽣列表的对象可转换成对应的***class_room***类/结构体, 其中学⽣列表可以⽤vector容器表⽰
class class_room
{
public:
string teacher_name;
std::vector<student> student_list;
};
3. 为了能够对这两个模型进⾏⾃由转换,需要对每个类/结构体分别提供两个函数
// 对于student对象
void from_json(const json& j, student& p)
{
j.at("name").get_to(p.name);
j.at("age").get_to(p.age);
j.at("phone").get_to(p.phone);
}
void to_json(json& j,const student& s)
{
j = json{{"name", s.name },{"age",s.age },{"phone", s.phone }};
}
//对于class_room对象
void from_json(const json& j, class_room& p)
{
j.at("teacher_name").get_acher_name);
j.at("teacher_name").get_acher_name);
for(auto&student_t : j["student_list"])
{
student s;
from_json(student_t, s);
p.student_list.push_back(s);
}
}
void to_json(json& j,const class_room& s)
{
python怎么读取json文件j = json{{"teacher_name", s.teacher_name }};
for(auto& student_t : s.student_list)
{
json j_student;
to_json(j_student, student_t);
j["student_list"].push_back(j_student);
}
}
当使⽤class_room字符串调⽤json的构造函数时,相应的to_json函数就会被调⽤,调⽤完成后对应的json对象就解析完成。
反过来,如果调⽤***get***或者***get_to***时,from_json⽅法将会被调⽤
4. 注意事项:
1. 上⾯3步的都应包含在同⼀个namespace中,否则nlohmann库将不能正确的进⾏转换。代码结构⽰例如下
namespace ns
{
class A
{
// ⼀些结构体变量
}
void from_json(const json& j, A& a)
{
// 转换的代码
}
void to_json(json& j,const A& a)
{
// 转换的代码
}
}
2. 需要⽤到这些转换的功能时,相应的头⽂件必须被包含,否则也不能转换成功
3. 访问json的元素时,尽量使⽤ at() ⽅法⽽不要使⽤ ***operator[]***, 因为如果当有key不存在时,at() ⽅法会抛出异常⽽
operator[] 不会
3. json字符串转换成数据对象
ns::class_room cr;
ns::from_json(commands, cr);
//接下来就可以针对对象进⾏操作了
std::cout << cr.student_list[0].age << std::endl;
cr.student_list[0].age +=10;
4. 数据对象转换
json j_2;
ns::class_room cr;
ns::to_json(j_2, cr);
关注【兰亭汇】即可获取完整代码~
感兴趣的同学可以看看。会不定时分享⼯作⽣活中的所见所闻~
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论