【C++】JsonCpp库

embedded/2025/1/12 8:42:47/

目录

前置知识

Json数据格式

JsonCpp介绍

jsoncpp%E5%BA%93-toc" style="margin-left:40px;">安装jsoncpp库

头文件

使用介绍

使用示例

序列化

反序列化


前置知识

Json数据格式

Json数据格式是一种数据交换格式,采用完全独立于编程语言的文本格式存储和表示数据。

例如:表示一个学生信息

{

        "姓名":"xxx",

        "年龄":18,

        "成绩":[88.5,99,58]

}

Json的数据类型包括对象,字符串,数字等 

  • 对象:使用花括号{ }括起来的表示一个对象
  • 数组:使用中括号[ ]括起来的表示一个数组
  • 字符串:使用常规双引号“”括起来的一个字符串
  • 数字:包括整型和浮点型,直接使用

JsonCpp介绍

jsoncpp%E5%BA%93">安装jsoncpp库

Linux环境下(ubuntu)

sudo apt-get install libjsoncpp-dev

头文件

在使用前,需要先引入jsoncpp的头文件

#include<jsoncpp/json/json.h>

使用介绍

JsonCpp库是用来实现Json数据格式的序列化和反序列化,主要涉及三个类:

1、Json::Value类:中间数据存储类

如果要将数据进行序列化,就需要先存储到Json::Value对象中;

如果要将数据进行反序列化,就是解析后,将数据对象放入到Json::Value对象中

如下是Json数据对象类的表示: 

class Json::Value{Value &operator=(const Value &other); //Value重载了[]和=,因此所有的赋值和获取
数据都可以通过Value& operator[](const std::string& key);//简单的⽅式完成 val["name"] = 
"xx";Value& operator[](const char* key);Value removeMember(const char* key);//移除元素const Value& operator[](ArrayIndex index) const; //val["score"][0]Value& append(const Value& value);//添加数组元素val["score"].append(88); ArrayIndex size() const;//获取数组元素个数 val["score"].size();std::string asString() const;//转string string name = val["name"].asString();const char* asCString() const;//转char* char *name = val["name"].asCString();Int asInt() const;//转int int age = val["age"].asInt();float asFloat() const;//转float float weight = val["weight"].asFloat();bool asBool() const;//转 bool bool ok = val["ok"].asBool();
};

2、序列化接口

  • Json::StreamWriter类:用于进行数据序列化
  • Json::StreamWriter::write() 序列化函数
  • Json::StreamWriterBuilder类:Json::StreamWriter工厂类,用于生产一个Json::StreamWriter对象
class JSON_API StreamWriter {virtual int write(Value const& root, std::ostream* sout) = 0;
}
//工厂类,生成一个StreamWriter对象
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {virtual StreamWriter* newStreamWriter() const;
}

PS:

virtual int write(要序列化的Json::Value对象, 输出流对象地址) = 0; 

  • 返回0序列化成功

 3、反序列接口

  • Json::CharReader反序列化类
  • Json::CharReader::parse()反序列化函数
  • Json::CharReaderBuilder 工厂类,用于生产一个Json::CharReader对象
class JSON_API CharReader {virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, std::string* errs) = 0;
}
//工厂类
class JSON_API CharReaderBuilder : public CharReader::Factory {virtual CharReader* newCharReader() const;
}

PS: 

virtual bool parse((序列化后的字符串)字符串的起始地址, 字符串的结束地址,存放解析结果的Json::Value对象的地址,erro信息)

  • 返回true反序列化成功

使用示例

序列化

#include <iostream>
#include <string>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
bool serialize(Json::Value &val,std::string &body)
{std::stringstream ss;//先实例化一个工厂类对象Json::StreamWriterBuilder swb;//获取一个StreamWriter对象std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());int ret=sw->write(val,&ss);if(ret!=0){std::cout<<"serialize failed!"<<std::endl;return false;}body=ss.str();return true;}
int main()
{Json::Value student;Json::Value fav;//描述爱好//填入爱好fav["书籍"]="骆驼祥子";fav["运动"]="打羽毛球";student["姓名"]="张三";student["年龄"]=19;//数组不能直接赋值,需要使用append方法student["成绩"].append(100);student["成绩"].append(100);student["成绩"].append(100);//嵌套一个对象student["爱好"]=fav;std::string body;if(serialize(student,body)){std::cout<<body<<std::endl;}return 0;
}

编译运行

g++ -std=c++11 jsoncpp_test.cc -o json -ljsoncpp

结果如下:

root@ubuntu:~/demo/jsoncpp# ./json 
{"姓名" : "张三","年龄" : 19,"成绩" : [100,100,100],"爱好" : {"书籍" : "骆驼祥子","运动" : "打羽毛球"}
}

注意:

  • Json::StreamWriterBuilder工厂类返回的是Json::StreamWriter的指针,因此我们使用完Json::StreamWriter对象后要记得释放,这里采用智能指针对其进行管理。

反序列化

bool unserialize(const std::string &body,Json::Value &val)
{//创建Json::CharReaderBuilder 工厂类Json::CharReaderBuilder crb;//获取一个Json::CharReader对象std::unique_ptr<Json::CharReader> cr(crb.newCharReader());std::string errs;bool ret=cr->parse(body.c_str(),body.c_str()+body.size(),&val,&errs);if(ret==false){std::cout<<"json unserialize failed:"<<errs<<std::endl;return false;}return true;
}
int main()
{std::string str=R"({"姓名":"张三","年龄":19,"成绩":[100,100,99]})";Json::Value val;if(unserialize(str,val)){std::cout<<"姓名:"<<val["姓名"].asString()<<std::endl;std::cout<<"年龄:"<<val["年龄"].asInt()<<std::endl;int sz=val["成绩"].size();for(int i=0;i<sz;i++){std::cout<<"成绩:"<<val["成绩"][i].asFloat()<<std::endl;}}return 0;
}


http://www.ppmy.cn/embedded/152887.html

相关文章

LeetCode 3297.统计重新排列后包含另一个字符串的子字符串数目 I:滑动窗口

【LetMeFly】3297.统计重新排列后包含另一个字符串的子字符串数目 I&#xff1a;滑动窗口 力扣题目链接&#xff1a;https://leetcode.cn/problems/count-substrings-that-can-be-rearranged-to-contain-a-string-i/ 给你两个字符串 word1 和 word2 。 如果一个字符串 x 重新…

python无需验证码免登录12306抢票 --selenium(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 [TOC](python无需验证码免登录12306抢票 --selenium(2)) 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 就在刚刚我抢的票&#xff1a;2025年1月8日…

JS DOM详解

DOM (文档对象模型) 文档对象模型 主要的职责是 处理网页中的标签(元素) 获取标签&#xff08;元素&#xff09;对象 document.getElementById(“id”) 根据标签的 ID 属性值 获取 指定的元素、 该方法 只能返回 一个标签。document.getElementsByTagName(“tag”) : 根据标签…

力扣-数组-108 将有序数组转换为二叉搜索树

解析 第一时间没思路&#xff0c;看了大佬的解析&#xff0c;首先数组有序&#xff0c;而平衡二叉搜索树又是左节点小于父节点小于右节点的&#xff0c;所以结合有序数组&#xff0c;不断二分就可以 代码 class Solution { public:TreeNode* sortedArrayToBST(vector<int…

Three.js 12中利用着色器进行材质加工深度解析

在Three.js这一强大的3D图形库中&#xff0c;着色器&#xff08;Shader&#xff09;是实现复杂视觉效果的关键工具。通过自定义着色器&#xff0c;开发者可以突破内置材质的限制&#xff0c;创造出独特且富有创意的材质效果。本文将深入探讨在Three.js 12中如何利用着色器对材质…

QT 将单线程改为线程池 端口扫描3.5

接上篇QT实现 端口扫描暂停和继续功能 3-CSDN博客 多线程与线程池的关系 多线程是基础: 线程池是基于多线程的概念实现的。线程池内部使用多个线程来并发执行任务。线程池优化多线程: 线程池通过复用线程和管理任务来优化多线程的使用&#xff0c;减少了线程创建和销毁的开销…

钓鱼攻击(Phishing)详解和实现 (网络安全)

钓鱼攻击&#xff08;Phishing&#xff09;详解和实现 钓鱼攻击是一种社会工程学攻击&#xff0c;攻击者通过伪装成可信任的实体诱使受害者泄露敏感信息&#xff0c;如用户名、密码、信用卡号等。以下详细介绍钓鱼攻击的原理、种类、实现方式&#xff0c;以及防御措施。 一、钓…

武汉火影数字|探秘数字展厅:开启沉浸式科技新体验

数字展厅&#xff0c;又叫做数字化展厅、多媒体数字化展厅等&#xff0c;是指以多媒体和数字化技术作为展示技术&#xff0c;使用最新的影视动画技术&#xff0c;结合独到的图形数字和多媒体技术&#xff0c;以各类新颖的技术吸引参观者&#xff0c;实现人机交互方式的展厅形式…