JSON是很常用的数据格式,在C++中我们可以使用nlohmann json做序列化和反序列化。
nlohmann json是一个跨平台的开源的C++ JSON解析库,只需要在项目中#include "json.hpp"文件就可以使用了。
Github上面的文档非常详细,你也可以通过本文对nlohmann json有个基本了解,本文涵盖了日常编码中会用json库处理的大部分操作,如构造json对象、查找键值、序列化与反序列。
github地址: https://github.com/nlohmann/json#serialization--deserialization
using nlohmann::json;
//方式一:
json j1;
j["name"]="LeBorn Jame";//字符串
j["number"]=23;//整数
j["man"]=true;//布尔值
j["children"]={"LeBorn Jr","Bryce Maximus","Zhuri"};//数组
j["behavior"]["funny"]="gigigigigigi";//对象中元素值
j["wife"]={{"name","Savannah Brinson"},{"man",false}};//对象
//方式二
json j2={
{"name","LeBorn Jame"},
{"number",23},
{"man",true},
{"children",{"LeBorn Jr","Bryce Maximus","Zhuri"}},
{"behavior",{{"funny","gigigigigigi"}};
{"wife",{{"name","Savannah Brinson"},{"man",false}}}
};
using nlohmann::json;
json j={
{"name","LeBorn Jame"},
{"number",23},
{"children",{"LeBorn Jr","Bryce Maximus","Zhuri"}},
{"man",true},
{"wife",{"name","Savannah Brinson"}}
};
auto name=j["name"].get<std::string>();//方式一
int number=0;
j["number"].get_to(number);//方式二
auto childOne = j["children"][0].get<std::string>();//获取数组元素方式一,越界后不会抛出异常,直接中断
auto childTwo=j["children"].at(1).get<std::string>();//越界后抛出异常
auto wifeName=j["wife"]["name"].get<std::string>();
//bool man=j["man"];//不推荐使用这种隐式转换的方式
using nlohmann::json;
json animalArray={"cat","dog"};//定义一个数组类型的json对象
animalArray.push_back("pig");//添加元素
animalArray.emplace_back("duck");//C++11新方式添加元素,减少申请内存
//使用is_array()函数判断对象类型,使用empty函数判断数量是否为空
if(animalArray.is_array() && !animalArray.empty())
{
auto size=animalArray.size();//使用size函数获取元素数量
auto animalLast=animalArray.at([size-1]).get<std::string>();
}
json animalObject={{"kind","dog"},{"height",50}};//定义一个对象类型的json对象
animalObject.emplace({"color","red"});//插入元素
animalObject.erase("kind");//删除键值
//判断是否含有某个键值方式一
if(animalObject.contains("height"))//通过contains函数判断是否包含某个key
{
auto height=animalObject["height"].get<double>();
}
//判断是否含有某个键值方式二
auto size=animalObject.count("height");//通过count函数计算某一个键的数量
if(size>0)
{
}
//判断是否含有某个键值方式三
auto iter=animalObject.find("height");//通过find函数查找某个键的迭代器
if(iter!=animalObject.end()
{
}
//遍历输出键值方式一
for(auto item:animalObject.items())
{
std::cout<<item.key()<<" "<<item.value()<<std::endl;
}
//遍历输出键值方式2
for(auto iter=animalObject.begin();iter!=animalObject.end();++iter)
{
std::cout<<iter->key()<<" "<<iter->value()<<std::endl;
}
//遍历输出键值方式3(C++17)
for(auto[key,value]:animalObject.keys())
{
std::cout<<key<<" "<<value<<std::endl;
}
using nlohmann::json;
//反序列化(Deserialization):_json/parse()
json j1="{"kind":"dog","height":50}"_json;//方式一,通过"_json"实现
json j2=R"({"kind":"dog","height":50})";//使用原生字符串关键字R来避免转移字符,但这一句并没有序列化,j2只保存字符串而已
json j3=json::parse(R"({"kind":"dog","height":50})");//方式二,通过静态函数"parse"实现。
//使用 parse 函数时,如果字符串不符合 json 规范导致解析失败,默认会抛出异常,可以使用 try...catch 结构捕获异常进行处理;或者设置 parse 函数的第三个函数参数为 false,此时解析失败不会抛出异常,但解析得到的结果为 null。
//序列化(Serialization):dump(number),number为打印出的空格数
std::string animal1=j1.dump();//animal1值为{"kind":"dog","height":50}
std::string animal2=j1.dump(4);
//animal2值为
// {
// "kind":"dog",
// "height":50,
// }
using nlohmann::json;
//反序列化(Deserialization):>>
json j1;
std::cin>>j1;
//序列化(Seriralization):<<
std::cout<<j1;
//上述操作适用于istream和ostream的子类,比如我们经常会用到的ifstream和ofstream
std::ifstream in(animals.json);//打开文件,关联到流in
json animals;
in>>animals;
animals.at(0)["height"]=60;//修改数据
in.close();
std::ofstream out(animal.json);//打开文件,关联到流out
out<<std::setw(4)<<animals;//输出信息,std::setw(4)用于设置增加打印空格
out.close();
在自定义对象命名空间中定义两个函数即可像basic value一样进行反序列化和序列化:from_json(const json& j,T& value)、to_json(json& j,const T& value)
//Animal.h文件
//定义Animal类,其包含两个成员变量kind与height
using nlohmann::json;
class Animal
{
public:
Animal(std::string kind,double height){
this->kind=kind;
this->height=height;
}
std::string kind;
double height;
}
//定义from_json(const json& j,T& value)函数,用于序列化
void from_json(const json& j,Animal& animal)
{
animal.kind=j["kind"].get<std::string>();
animal.height=j["height"].get<double>();
}
//定义to_json(json& j,const T& value)函数,用于反序列化
void to_json(json& j,const Animal& animal)
{
j["kind"]=animal.kind;
j["height"]=animal.height;
}
//main.cpp文件
int main()
{
Animal animal{"dog",50};
nlohmnn::json j=animal;//像basic value一样将自定义对象赋值给json value
j["height"]=60;//修改数据
Animal animalNew = j.get<Animal>();//像basic value一样通过get函数获取值,将其值直接赋值给自定义对象
std::cout<<animal.height;//输出60
return 0;
}