侧边栏壁纸
  • 累计撰写 185 篇文章
  • 累计创建 77 个标签
  • 累计收到 17 条评论

目 录CONTENT

文章目录

C++中对JSON格式的解析以及序列化和反序列化

码峰
2022-07-19 / 0 评论 / 3 点赞 / 2,325 阅读 / 1,581 字 / 正在检测是否收录...
广告 广告

前言

JSON是很常用的数据格式,在C++中我们可以使用nlohmann json做序列化和反序列化。
nlohmann json是一个跨平台的开源的C++ JSON解析库,只需要在项目中#include "json.hpp"文件就可以使用了。
github上面的文档非常详细,你也可以通过本文对nlohmann json有个基本了解,本文涵盖了日常编码中会用json库处理的大部分操作,如构造json对象、查找键值、序列化与反序列。
github地址: https://github.com/nlohmann/json#serialization--deserialization

nlohmann json基础操作

由basic value创建json value

 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}}}
 };

由json value得到basic value

 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"];//不推荐使用这种隐式转换的方式

像操作stl container一样操作json value

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;
}

序列化与反序列化(Serialization/Deserialization)

json value和string

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,
// }

json value和streams

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();

json value和自定义对象

在自定义对象命名空间中定义两个函数即可像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;
}

3
广告 广告

评论区