应使用 Json::CharReaderBuilder 构造解析器并检查 parseFromStream 返回值,错误时通过 errs 获取详细信息,避免直接访问未成功解析的空对象。

怎么用 JsonCpp 读取字符串里的 JSON
JsonCpp 不自带解析器,得手动构造 Json::CharReaderBuilder 或用旧版 Json::Reader。新版推荐前者,更安全、支持 Unicode。
常见错误是直接传 raw string 给 parse() 却忽略返回值,导致解析失败却继续访问空对象:
Json::Value root;
Json::CharReaderBuilder builder;
std::string errs;
std::istringstream ss("{\"name\":\"alice\",\"age\":30}");
if (!Json::parseFromStream(builder, ss, &root, &errs)) {
// 必须检查!errs 里有具体错误位置和原因
std::cerr << "JSON parse error: " << errs << std::endl;
return;
}-
Json::CharReaderBuilder默认启用strictMode,不接受 trailing comma、单引号、注释等非标准写法 - 如果输入来自网络或文件,注意编码:JsonCpp 只处理 UTF-8,别传 GBK 或 UTF-16
- 不要用
Json::Reader(已弃用),它在 v1.9+ 中被标记为 deprecated,且线程不安全
如何安全访问嵌套字段并避免崩溃
直接链式调用 root["data"]["items"][0]["id"] 很危险——任一中间层缺失都会返回空 Json::Value,但 asInt() 或 asString() 在空值上调用会抛 std::logic_error。
正确做法是逐层检查 isNull() 和 isMember(),或用带默认值的 get():
立即学习“C++免费学习笔记(深入)”;
本书是全面讲述PHP与MySQL的经典之作,书中不但全面介绍了两种技术的核心特性,还讲解了如何高效地结合这两种技术构建健壮的数据驱动的应用程序。本书涵盖了两种技术新版本中出现的最新特性,书中大量实际的示例和深入的分析均来自于作者在这方面多年的专业经验,可用于解决开发者在实际中所面临的各种挑战。 本书内容全面深入,适合各层次PHP和MySQL开发人员阅读,既是优秀的学习教程,也可用作参考手册。
// 安全写法:提供默认值,类型自动转换
int id = root.get("data", Json::Value::nullRef)
.get("items", Json::Value::nullRef)
.get(0, Json::Value::nullRef)
.get("id", Json::Value(0)).asInt();
// 或更清晰的判断
if (root.isObject() &&
root.isMember("user") &&
root["user"].isObject() &&
root["user"].isMember("email")) {
std::string email = root["user"]["email"].asString();
}
-
Json::Value::nullRef是轻量占位符,比构造新Json::Value()更高效 -
get(key, defaultValue)的defaultValue类型必须和期望访问类型兼容,否则可能静默转成 0 或空串 - 数组索引越界不会报错,
array[100]返回空值,务必先用array.size()判断
怎么把 C++ 对象序列化成 JSON 字符串
输出控制权在 Json::StreamWriterBuilder,不是简单调 toString() 就完事。默认格式是紧凑型(无换行缩进),调试时很难看。
Json::StreamWriterBuilder builder; builder["indentation"] = " "; // 注意:必须是字符串,不能是 \t builder["commentStyle"] = "None"; // 禁用注释(默认可能加 /* ... */) std::string json_str = Json::writeString(builder, root);
- 如果要兼容老系统或日志友好,设
builder["indentation"] = ""回到紧凑模式 -
root.toStyledString()是快捷方式,但无法定制,且内部固定用 4 空格缩进、启用注释,不适合生产环境 - 浮点数精度默认 17 位,如需控制小数位数,得先转成字符串再塞进
Json::Value,JsonCpp 不提供setPrecision()
链接和编译时最容易漏掉的细节
JsonCpp 编译后分静态库 jsoncpp 和头文件两部分,CMake 项目常只 link 库却忘了 include 目录,报 Json/json.h: No such file。
CMakeLists.txt 正确写法示例:
find_package(jsoncpp REQUIRED)
target_link_libraries(myapp PRIVATE jsoncpp_lib)
target_include_directories(myapp PRIVATE ${jsoncpp_INCLUDE_DIRS})- Ubuntu/Debian 上装的是
libjsoncpp-dev,但头文件路径是/usr/include/jsoncpp/json/json.h,所以 include 时得写#include,不是 - Windows 下若用 vcpkg,包名是
jsoncpp,但生成的库名可能是jsoncpp.lib或jsoncpp_static.lib,取决于是否开启JSONCPP_LIB_BUILD_SHARED - Release 模式下,JsonCpp 会关掉部分运行时检查(如类型断言),所以开发期出现的
LogicError在 Release 可能变成静默错误或崩溃
最常被跳过的一步:没验证输入 JSON 是否合法就直接 parse,结果程序在用户上传的畸形数据上当场退出。解析前加个 std::string::find_first_not_of(" \t\r\n") != std::string::npos 至少能防空输入。










