参考:简单的用法
项目地址: https://github.com/nlohmann/json
前一篇文章用的是json-c,使用起来还算凑合,但是绝对的不能算是优雅,尤其是跟脚本语言相比。
很多时候我们希望能够封装类,优雅的实现JSON 的转换,我也是在阅读violetMiner源码时候发现人家用的是啥。(读代码是个好习惯),
1)首先看一下效果:
class address {
public:
std::string street;
int housenumber;
int postcode;
public:
// 类名,成员1,成员2,成员3
NLOHMANN_DEFINE_TYPE_INTRUSIVE(address, street, housenumber, postcode)
};
void test4()
{
address addr{"robin's house", 12456, 100091};
json jsonAddr = addr;
cout << jsonAddr.dump() << endl;
}
看看,对于简单的类,使用了一个宏就搞定了;那么如果不用宏大概是个啥子样子呢?
2)使用普通的JSON库,大概都是这个样子滴
// 结构体的转换
struct person {
std::string name;
std::string address;
int age;
};
// 比较传统的转换方法,大多json库都是类似
void test1()
{
person p = { "Ned Flanders", "744 Evergreen Terrace", 60 };
json j;
j["name"] = p.name;
j["address"] = p.address;
j["age"] = p.age;
string str = j.dump();
person user1 = person{
j["name"].get<std::string>(),
j["address"].get<std::string>(),
j["age"].get<int>()
};
}
///
3)但是nlohmann::json还可以自己定义下转换过程:
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);
}
void test2()
{
person p{ "Ned Flanders", "744 Evergreen Terrace", 60 };
// conversion: person -> json
json j = p;
std::cout << j << std::endl;
auto p2 = j.get<person>();
//cout << p2;
}
这2个转换函数就是其中的关键,而在上文中看到的宏就是自动展开为这两个函数;
3)到这里,其实还有一个重要的问题我们没有提及,那就是万一JSON格式不对怎么办,比如我遇到的服务器返回的字符串缺少某个字段,我们需要异常处理,像这样:
// 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";
//j["sex"] = "male";
j.erase("sex"); // 删除不存在的值,无异常
try
{
// test does not exist
//string sex = j["sex"];
string sex;
sex = j.at("sex");
cout << sex << endl;
}
catch (json::exception& e)
{
// output exception information
std::cout << "message: " << e.what() << '\n'
<< "exception id: " << e.id << std::endl;
}
4) 最后在看一下,怎么像脚本语言一样处理JSON:
void initSetJson()
{
json j2 = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"answer", { {"everything", 42} } },
{"list", {1, 0, 2} },
{"object", {
{"currency", "USD"},
{"value", 42.99}
}}
};
string message = j2.dump();
cout << message << endl;
}
是不是挺惊艳?
回头再测试一下与json-c相比哪个快?