文章目录
- 本篇摘要
-
- [一、Jsoncpp 是什么?](#一、Jsoncpp 是什么?)
- [二、环境准备:如何安装 Jsoncpp?](#二、环境准备:如何安装 Jsoncpp?)
- [三、Jsoncpp 的核心功能与代码示例](#三、Jsoncpp 的核心功能与代码示例)
- 四、常见问题与注意事项
- 五、Jsoncpp核心接口总结
- 本篇小结

本篇摘要
本文详解C++生态经典库Jsoncpp的核心用法,涵盖环境搭建、新版API解析/生成功能(如CharReader/StreamWriterBuilder)、类型安全操作及文件交互,来帮助读者快速上手jsoncpp。
前言:
JSON(JavaScript 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串的形式就是一层套一层(通过花括号),如果是有数组也就是通过中括号规划出来,其次就是默认存储的时候以十六进制形式存储,因此传输起来也是比较方便的。
对应测试源码:
cpp
#include <json/json.h>
#include <iostream>
#include <sstream>
#include <memory>
bool Serialize(Json::Value &jn, std::string &res_str)
{
Json::StreamWriterBuilder swb;
std::unique_ptr<Json::StreamWriter> psw(swb.newStreamWriter());
std::stringstream ss;
int ret = psw->write(jn, &ss);
if (ret != 0)
{
std::cout << "Json反序列化失败!\n";
return false;
}
res_str = ss.str();
return true;
}
bool UnSerialize(std::string &res_str, Json::Value &jn)
{
Json::CharReaderBuilder crb;
std::shared_ptr<Json::CharReader> cr(crb.newCharReader());
std::string errs;
int ret = cr->parse(res_str.c_str(), res_str.c_str() + res_str.size(), &jn, &errs);
if (ret == false)
{
std::cout << "json反序列化失败: " << errs << std::endl;
return false;
}
return true;
}
int main()
{
char name[] = "张三";
int age = 18;
float score[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;
bool ret1 = Serialize(stu, res);
if (ret1 == false)
return -1;
std::cout << res << std::endl;
Json::Value uts;
bool ret2 = UnSerialize(res, uts);
if (ret2 == false)
return -1;
std::cout << uts["姓名"].asString() << std::endl;
std::cout << uts["年龄"].asInt() << std::endl;
int sz = uts["成绩"].size();
for (int i = 0; i < sz; i++)
{
std::cout << uts["成绩"][i].asFloat() << std::endl;
}
return 0;
}
解释下:
- 首先是构建对应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):
cpp#include <fstream> std::ifstream file("config.json"); std::string jsonStr((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); // 然后用 Json::parseFromStream 解析 jsonStr - 实际项目中常需要从文件加载 JSON 或保存 JSON 到文件。可以使用
五、Jsoncpp核心接口总结
核心类/模块总结
| 类/模块 | 用途 | 头文件 |
|---|---|---|
Json::Value |
JSON 数据的万能容器(对象/数组/字符串/数字等) | <json/json.h> |
Json::CharReaderBuilder |
解析 JSON 字符串 的配置器(新版推荐,线程安全) | <json/json.h> |
Json::CharReader |
实际执行解析的底层类(通常通过 CharReaderBuilder 间接使用) |
<json/json.h> |
Json::StreamWriterBuilder |
生成 JSON 字符串 的配置器(新版推荐,线程安全) | <json/json.h> |
Json::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* errs<br>); |
将 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& root<br>); |
将 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::Value |
std::string Json::Value::asString() const |
将字段值转为 C++ 字符串 | 取 JSON 中的文本字段(如 "name": "Alice") |
std::string name = root["name"].asString(); |
|
root["字段名"].asInt() |
Json::Value |
int Json::Value::asInt() const |
将字段值转为 C++ 整数 | 取 JSON 中的整数字段(如 "age": 25) |
int age = root["age"].asInt(); |
|
root["字段名"].asBool() |
Json::Value |
bool Json::Value::asBool() const |
将字段值转为 C++ 布尔值 | 取 JSON 中的布尔字段(如 "isValid": true) |
bool valid = root["isValid"].asBool(); |
|
root["字段名"].asDouble() |
Json::Value |
double Json::Value::asDouble() const |
将字段值转为 C++ 浮点数 | 取 JSON 中的浮点数字段(如 "price": 9.9) |
double price = root["price"].asDouble(); |
|
root.isMember("字段名") |
Json::Value |
bool Json::Value::isMember(const std::string& key) const |
检查 JSON 对象是否包含某个字段 | 避免访问不存在的字段导致错误 | if (root.isMember("name")) { ... } |
|
root.isArray() |
Json::Value |
bool Json::Value::isArray() const |
判断字段是否为 JSON 数组 | 安全遍历数组元素 | if (root["skills"].isArray()) { ... } |
|
root.isObject() |
Json::Value |
bool Json::Value::isObject() const |
判断字段是否为 JSON 对象 | 安全访问嵌套对象 | if (root["address"].isObject()) { ... } |
|
rootsize_t index |
通过索引访问 JSON 数组的元素 | 取数组中的某个值(如第 0 个元素) | std::string skill = root["skills"][0].asString(); |
|||
root["数组字段"].size() |
Json::Value |
size_t Json::Value::size() const |
获取 JSON 数组的长度 | 遍历数组时获取元素数量 | for (size_t i=0; i<root["skills"].size(); i++) { ... } |
|
rootconst std::string& key |
访问嵌套 JSON 对象的字段(多层对象) | 取嵌套结构中的字段(如 "address.city") |
std::string city = root["address"]["city"].asString(); |
|||
| 4. 配置生成/解析格式 | builder["indentation"] = " " |
StreamWriterBuilder / CharReaderBuilder |
builder["indentation"] = " "(设置缩进字符串) |
控制生成的 JSON 字符串格式(缩进美化) | 让生成的 JSON 可读性高(调试用) | builder["indentation"] = " "; |
builder["indentation"] = "" |
StreamWriterBuilder / CharReaderBuilder |
builder["indentation"] = ""(空字符串无缩进) |
控制生成的 JSON 字符串格式(紧凑无缩进) | 生成紧凑 JSON(节省空间/网络传输) | builder["indentation"] = ""; |
本篇小结
本篇详细接受jsoncpp如何安装,如何使用,以及简单例子介绍常见接口,还有就是最后常见的重要结构,来帮助读者快速上手jsoncpp书写。