数据织网者:Jsoncpp库深度解析——从C++原生JSON处理到工程级数据交互实战全攻略
文章目录本篇摘要一、Jsoncpp 是什么二、环境准备如何安装 Jsoncpp三、Jsoncpp 的核心功能与代码示例四、常见问题与注意事项五、Jsoncpp核心接口总结核心类/模块总结常用接口功能总结本篇小结本篇摘要本文详解C生态经典库Jsoncpp的核心用法涵盖环境搭建、新版API解析/生成功能如CharReader/StreamWriterBuilder、类型安全操作及文件交互来帮助读者快速上手jsoncpp。前言JSONJavaScript Object Notation是现代软件开发中最常用的轻量级数据交换格式之一而Jsoncpp是 C 生态中最经典、最稳定的 JSON 处理库。无论你是开发配置文件解析、API 数据交互还是游戏存档管理掌握 Jsoncpp 都能让你高效处理 JSON 数据。一、Jsoncpp 是什么Jsoncpp是一个开源的 C 库专门用于解析、生成和操作 JSON 数据。它的特点是纯 C 实现无需依赖第三方运行时环境。API 设计简洁符合 C 开发者的使用习惯。跨平台支持Windows/Linux/macOS兼容主流编译器GCC/Clang/MSVC。稳定性高被广泛应用于游戏开发如 Unreal Engine 插件、嵌入式系统和后端服务。二、环境准备如何安装 Jsoncpp获取源码访问 Jsoncpp 的官方 GitHub 仓库https://github.com/open-source-parsers/jsoncpp(点击即跳转)下载最新版本的源码压缩包如jsoncpp-master.zip解压到本地目录。编译为静态库以 Windows Visual Studio 为例打开解压后的文件夹进入jsoncpp-master\makefiles\vs71根据你的 VS 版本选择如vs2022。用 Visual Studio 打开jsoncpp.sln工程文件。在解决方案配置中选择Release模式编译lib_json项目生成静态库文件如jsoncpp.lib。编译完成后头文件在include/json目录库文件在libs目录。配置你的项目将include/json目录添加到项目的头文件搜索路径如 Visual Studio 中的附加包含目录。将编译生成的jsoncpp.lib添加到项目的库文件搜索路径如附加库目录并在链接器输入中添加jsoncpp.lib。其他平台Linux/macOS用户可通过包管理器直接安装如sudo apt-get install libjsoncpp-dev。三、Jsoncpp 的核心功能与代码示例Jsoncpp 的核心是三个类Json::Value表示 JSON 数据的通用容器可以是对象、数组、字符串、数字等。Json::Reader旧版/Json::CharReader新版解析 JSON 字符串为Json::Value对象。Json::StyledWriter旧版/Json::StreamWriterBuilder新版将Json::Value对象转换为格式化的 JSON 字符串。注意Jsoncpp 1.9.0 及以上版本推荐使用CharReader和StreamWriterBuilder更现代且线程安全以下示例基于新版 API。简单使用测试效果这里可以看到转化成json串的形式就是一层套一层通过花括号如果是有数组也就是通过中括号规划出来其次就是默认存储的时候以十六进制形式存储因此传输起来也是比较方便的。对应测试源码#includejson/json.h#includeiostream#includesstream#includememoryboolSerialize(Json::Valuejn,std::stringres_str){Json::StreamWriterBuilder swb;std::unique_ptrJson::StreamWriterpsw(swb.newStreamWriter());std::stringstream ss;intretpsw-write(jn,ss);if(ret!0){std::coutJson反序列化失败\n;returnfalse;}res_strss.str();returntrue;}boolUnSerialize(std::stringres_str,Json::Valuejn){Json::CharReaderBuilder crb;std::shared_ptrJson::CharReadercr(crb.newCharReader());std::string errs;intretcr-parse(res_str.c_str(),res_str.c_str()res_str.size(),jn,errs);if(retfalse){std::coutjson反序列化失败: errsstd::endl;returnfalse;}returntrue;}intmain(){charname[]张三;intage18;floatscore[3]{88,89.5,99};Json::Value stu;stu[姓名]name;stu[年龄]age;stu[成绩].append(score[0]);stu[成绩].append(score[1]);stu[成绩].append(score[2]);std::string res;boolret1Serialize(stu,res);if(ret1false)return-1;std::coutresstd::endl;Json::Value uts;boolret2UnSerialize(res,uts);if(ret2false)return-1;std::coututs[姓名].asString()std::endl;std::coututs[年龄].asInt()std::endl;intszuts[成绩].size();for(inti0;isz;i){std::coututs[成绩][i].asFloat()std::endl;}return0;}解释下首先是构建对应json对象也就是定义Json::Value对象然后这里是可以支持嵌套的也就是可以把这个对象当成对象map来用即可也就是key-value结构对应的value可以是数组也就是必须通过append来添加对应成员value也可以是json对象类似循环嵌套接口因此可以把对应描述事物的逻辑结构转化成这种嵌套逻辑模式最后按照格式转化成json对象在最后变成json串即可。StreamWriterBuilder创建StreamWriter对象调用write接口来完成对应的把json对象写成对应json串通过stringstream流。CharReaderBuilder创建对应的CharReader来调用对应的parse接口把对应json串解析到对应传入的json对象里面。其次就是以json对象形式访问的对应的成员的时候如果要拿到里面的值就是直接类似asString把它转化成对应类型进行后续操作即可。四、常见问题与注意事项旧版 vs 新版 API旧版如Json::Reader和Json::StyledWriter在 1.9.0 之前常用但新版Json::CharReader和Json::StreamWriterBuilder更安全且线程友好推荐优先使用。如果使用旧版需包含json/reader.h和json/writer.h但新版已统一到json/json.h。类型安全访问字段时务必用正确的asXXX()方法如asString()、asInt()否则可能导致运行时错误。如果字段可能不存在先用root.isMember(字段名)检查是否存在或用root.get(字段名, 默认值)提供默认值如root.get(age, 0).asInt()。文件读写实际项目中常需要从文件加载 JSON 或保存 JSON 到文件。可以使用std::ifstream读取文件内容到字符串再用上述解析方法写入时则将生成的 JSON 字符串通过std::ofstream保存到文件。如从文件读取 JSON#includefstreamstd::ifstreamfile(config.json);std::stringjsonStr((std::istreambuf_iteratorchar(file)),std::istreambuf_iteratorchar());// 然后用 Json::parseFromStream 解析 jsonStr五、Jsoncpp核心接口总结核心类/模块总结类/模块用途头文件Json::ValueJSON 数据的万能容器对象/数组/字符串/数字等json/json.hJson::CharReaderBuilder解析 JSON 字符串的配置器新版推荐线程安全json/json.hJson::CharReader实际执行解析的底层类通常通过CharReaderBuilder间接使用json/json.hJson::StreamWriterBuilder生成 JSON 字符串的配置器新版推荐线程安全json/json.hJson::StreamWriter实际执行生成的底层类通常通过StreamWriterBuilder间接使用json/json.h常用接口功能总结功能分类接口/类所属模块接口原型/关键方法用途说明典型使用场景一行代码示例1. 解析 JSON 字符串Json::CharReaderBuilder解析模块Json::CharReaderBuilder builder;创建 JSON 解析器的配置对象线程安全解析 JSON 字符串前必须初始化Json::CharReaderBuilder builder;Json::parseFromStream解析模块bool Json::parseFromStream(br const Json::CharReaderBuilder builder,br const char* begin, const char* end,br Json::Value* root,br std::string* errsbr);将 JSON 字符串begin到end解析为Json::Value对象错误信息存到errs从文件/网络读取的 JSON 字符串转 C 对象Json::parseFromStream(builder, jsonStr.data(), jsonStr.data()jsonStr.size(), root, errs);Json::CharReader解析模块底层通常不直接使用通过CharReaderBuilder调用实际执行解析的底层类底层扩展或特殊需求新手一般不用-2. 生成 JSON 字符串Json::StreamWriterBuilder生成模块Json::StreamWriterBuilder builder;创建 JSON 生成器的配置对象线程安全生成 JSON 字符串前必须初始化Json::StreamWriterBuilder builder;Json::writeString生成模块std::string Json::writeString(br const Json::StreamWriterBuilder builder,br const Json::Value rootbr);将Json::Value对象转换为格式化的 JSON 字符串可读性好将 C 数据结构保存为 JSON 文件/网络传输std::string jsonStr Json::writeString(builder, root);Json::StreamWriter生成模块底层通常不直接使用通过StreamWriterBuilder调用实际执行生成的底层类底层扩展或特殊需求新手一般不用-3. 操作 Json::Value解析后的数据rootconst std::string key通过键名访问 JSON 对象的字段返回Json::Value取对象中的字符串、数字等字段值std::string name root[name].asString();root[字段名].asString()Json::Valuestd::string Json::Value::asString() const将字段值转为 C 字符串取 JSON 中的文本字段如name: Alicestd::string name root[name].asString();root[字段名].asInt()Json::Valueint Json::Value::asInt() const将字段值转为 C 整数取 JSON 中的整数字段如age: 25int age root[age].asInt();root[字段名].asBool()Json::Valuebool Json::Value::asBool() const将字段值转为 C 布尔值取 JSON 中的布尔字段如isValid: truebool valid root[isValid].asBool();root[字段名].asDouble()Json::Valuedouble Json::Value::asDouble() const将字段值转为 C 浮点数取 JSON 中的浮点数字段如price: 9.9double price root[price].asDouble();root.isMember(字段名)Json::Valuebool Json::Value::isMember(const std::string key) const检查 JSON 对象是否包含某个字段避免访问不存在的字段导致错误if (root.isMember(name)) { ... }root.isArray()Json::Valuebool Json::Value::isArray() const判断字段是否为 JSON 数组安全遍历数组元素if (root[skills].isArray()) { ... }root.isObject()Json::Valuebool Json::Value::isObject() const判断字段是否为 JSON 对象安全访问嵌套对象if (root[address].isObject()) { ... }rootsize_t index通过索引访问 JSON 数组的元素取数组中的某个值如第 0 个元素std::string skill root[skills][0].asString();root[数组字段].size()Json::Valuesize_t Json::Value::size() const获取 JSON 数组的长度遍历数组时获取元素数量for (size_t i0; iroot[skills].size(); i) { ... }rootconst std::string key访问嵌套 JSON 对象的字段多层对象取嵌套结构中的字段如address.citystd::string city root[address][city].asString();4. 配置生成/解析格式builder[indentation] StreamWriterBuilder/CharReaderBuilderbuilder[indentation] 设置缩进字符串控制生成的 JSON 字符串格式缩进美化让生成的 JSON 可读性高调试用builder[indentation] ;builder[indentation] StreamWriterBuilder/CharReaderBuilderbuilder[indentation] 空字符串无缩进控制生成的 JSON 字符串格式紧凑无缩进生成紧凑 JSON节省空间/网络传输builder[indentation] ;本篇小结本篇详细接受jsoncpp如何安装如何使用以及简单例子介绍常见接口还有就是最后常见的重要结构来帮助读者快速上手jsoncpp书写。