🌈欢迎来到C++专栏~~Jsoncpp上手
- (꒪ꇴ꒪(꒪ꇴ꒪ )🐣,我是Scort
- 🌍博客主页:张小姐的猫~江湖背景
- 快上车🚘,握好方向盘跟我有一起打天下嘞!
- 🎉🎉欢迎持续关注!

Jsoncpp上手
- 🌈欢迎来到C++专栏~~Jsoncpp上手
- [一. Json简介](#一. Json简介)
- [二. JsonCpp](#二. JsonCpp)
- 📢写在最后

一. Json简介
JSON(JavaScriptObjectNotation)是⼀种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的⼀个自子集,但尽管它来源于JavaScript,JSON是独立于语言的,可以被多种编程语言读取。以下是关于JSON的⼀些关键点:

json
{
"name": "John Doe",
"age": 30,
"is_student": false,
"skills": ["JavaScript", "Python", "C++"],
"address":
{
"street": "123 Main St",
"city": "Anytown",
"state": "CA"
}
}

Json常用于序列化
- 序列化:将数据对象,按照指定的格式组织成为一个二进制数据串
- 反序列化:将一个二进制数据串,按照指定格式解析得到其中的数据对象
二. JsonCpp
JsonCpp是⼀个高性能的JSON库,用于处理JSON数据。它提供了完整的JSON标准支持,包括解析JSON字符串、生成JSON字符串、读写JSON对象和数组等功能

对应的头文件是:
cpp
#include <jsoncpp/json/json.h>
编译时记得要链接库 :-ljsoncpp
1️⃣典型类:Value
Json::Value类是中间数据转储类 ,如果要针对多个数据进行序列化 ,就要先将各个数据存储到Value对象中,针对Value来进行序列化
如果要针对Json字符串进行反序列化,内部会进行解析,将结果都存储到Value对象里
常用接口有:[]运算符重载
cpp
json::Value val;
val["姓名"] = "卢本伟";
val["年龄"] = "33";
append接口:添加数组元素
c
val["成绩"].append(77.5);
数据获取呢?
cpp
auto name = val["姓名"].asString();
数组元素获取:
cpp
val["成绩"].size() //获取数组元素个数
auto sum = val["成绩"][0].asDouble();
那么怎么判断这个字段是什么类型呢?
cpp
bool isNull() const;
bool isArray() const;
bool isObject() const;
获取序列化后的数据:
cpp
String toStyledString() const;
上手体验一下:
cpp
#include <jsoncpp/json/json.h>
int main()
{
Json::Value val;
val["name"] = "DeepSeek-chat";
val["desc"] = "一款实用性强,功能强大的聊天模型";
val["model"] = "deepseek-3.5";
val["apikey"] = "sk-xxxx";
val["baseurl"] = "https://api.deepseek.cn/v1";
std::string str = val.toStyledString();
std::cout << str << std::endl;
return 0;
}

2️⃣序列化
此处涉及了两个类
StreamWriter:序列化类StreamWriterBuilder类:StreamWriter建造者类- 构造接口 :
newStreamWriter()
通过StreamWriterBuilder类来构建出序列化类StreamWriter来进行序列化
其中包含了write函数:------ 通常不会失败
cpp
write(Value const& root, OStream* sout)
将一个jsonValue对象内部的数据按照指定格式,序列化之后输入到输出流里,我们从输出流中取出对应的数据
3️⃣反序列化
涉及了Char Reader类:反序列化类
也用到了一个parse函数:
cpp
bool parse(char const* beginDoc, char const* endDoc, Value* root,String* errs)
- 给上字符串的起始和结束位置,根据其中的内容做反序列化解析,解析后的结果存储在
root对象中 errs是反序列化失败的原因
同理Char Reader类也无法直接构造,是由Char ReaderBuilder类:Char Reader建造者类来进行构造
Char Reader类:反序列化类Char ReaderBuilder类:Char Reader建造者类- 构造接口 :
newCharReader
✋️动手实践
操作流程:
- 实例化建造者对象
- 构造对象
- 序列化 & 反序列化
序列化:
cpp
#include <jsoncpp/json/json.h>
int main()
{
Json::Value val;
val["name"] = "DeepSeek-chat";
val["desc"] = "一款实用性强,功能强大的聊天模型";
val["model"] = "deepseek-3.5";
val["apikey"] = "sk-xxxx";
val["baseurl"] = "https://api.deepseek.cn/v1";
//1.实例化建造者对象
Json::StreamWriterBuilder builder;
Builder["indentation"]= "";
//2.构造对象
std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
//3.序列化
std::stringstream ss;
int ret = writer->write(val, &ss);//返回0表示成功
if(ret != 0){
std::cout << "write json failed" << std::endl;
return -1;
}
std::string str = ss.str();
std::cout << str << std::endl;
return 0;
}

可以加上下面,让输出变成紧凑单行格式(无缩进无换行)
cpp
Builder["indentation"]= "";

反序列化动手:
cpp
#include <jsoncpp/json/json.h>
int main()
{
//R"() 代表原始字符串
std::string str = R"({
"name": "DeepSeek-chat",
"desc": "DeepSeek-3.5",
"model": ["deepseek-3.5", "deepseek-3.5-16k", "deepseek-3.5-8k"]
})";
Json::CharReaderBuilder Builder;
std::unique_ptr<Json::CharReader> reader(Builder.newCharReader());
Json::Value val;
std::string errs;
bool ret = reader->parse(str.c_str(), str.c_str() + str.size(), &val, &errs);
if(!ret){
std::cout << "parse json failed, errs: " << errs << std::endl;
return -1;
}
std::cout << val["name"].asString() << std::endl;
std::cout << val["desc"].asString() << std::endl;
if(val["model"].isArray()){
for(int i = 0; i < val["model"].size(); i++){
std::cout << val["model"][i].asString() << std::endl;
}
}
}

📢写在最后

