【C++开发脚手架】 —— Jsoncpp上手

🌈欢迎来到C++专栏~~Jsoncpp上手


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

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

📢写在最后

相关推荐
小羊没烦恼!1 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
weilx12341 天前
C++笔记-文件IO-<fcntl.h>
c++
俊昭喜喜里1 天前
java中的继承和多态的区别
java
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
未济1 天前
linux 配置环境变量
linux
傲世仙尊1 天前
目录即文件-Ext文件系统收尾篇
linux·c语言
譕痕1 天前
JSONObject与JSONArray封装数据格式区别
java·json
虎头金猫1 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码1 天前
别再前后端各写一套表单校验了
java·后端