最直接办法是调用 Json::Reader::parse() 并检查返回值,再用 getFormattedErrorMessages() 获取详细错误;它不抛异常、不支持 string_view、无法自动处理 BOM,且空或纯空白字符串会导致静默失败。

用 jsoncpp 的 Json::Reader 捕获解析失败
最直接的办法是尝试解析,靠异常或返回值判断是否合法。但注意:Json::Reader 默认不抛异常,而是通过 parse() 返回 bool,且必须配合 getFormattedErrorMessages() 查错——很多人漏掉这步,误以为返回 false 就一定是格式错误,其实也可能是内存不足或输入为空。
-
Json::Reader不支持 C++17 以后的std::string_view,传入前得确保是std::string或 C 字符串 - 如果字符串含 BOM(如 UTF-8 带 EF BB BF),
Json::Reader会直接失败,需手动 strip - 空字符串、纯空白(
" \t\n")都算无效,但parse()对后者返回false且无明确提示,建议先trim()
用 nlohmann/json 的 json::parse() 配合 try/catch
现代项目更推荐 nlohmann/json,它默认抛 json::parse_error 异常,信息更准。但别只 catch std::exception——它还可能抛 json::type_error(比如对非对象调用 at()),而格式错误只对应 parse_error。
- 构造函数
json j = json::parse(str)在失败时抛异常;若用json::parse(str, nullptr, false)则返回json::value_t::discarded,适合不想用异常的场景 - 该库自动处理 BOM,也支持
string_view,但要求编译器支持 C++11 以上(C++17 更稳) - 性能上,小字符串(nlohmann 的栈分配策略略优,但频繁解析需注意临时
json对象的析构开销
避免用正则“模拟”JSON校验
网上有些正则表达式试图匹配 JSON 结构,比如 ^(\{.*\}|\[.*\])$,这完全不可靠。JSON 允许嵌套、转义、Unicode、注释(非标准但常见)、尾随逗号(某些解析器容忍),正则无法覆盖所有合法边界情况,反而会漏判或误报。
- 真正有效的 JSON 可能包含
"key": "a\"b"、"\u4f60\u597d"、甚至{ "x": null }——这些正则基本没法准确识别 - 即使加上复杂断言,也无法替代语法分析器对括号配对、引号闭合、数值格式(如
1e3、-.5)的检查 - 唯一能接受正则的场景:做前端快速预筛(比如排除明显不含
{或[的请求体),但后端仍必须用真实解析器验证
注意 std::string 编码与 JSON 要求的冲突
C++ 的 std::string 是字节容器,不保证 UTF-8 正确性。如果原始字符串来自用户输入、文件读取或网络接收,可能含非法 UTF-8 序列(如孤立的 continuation byte),这时即使语法正确,nlohmann/json 也会抛 parse_error(错误码 101)。
立即学习“C++免费学习笔记(深入)”;
- 不要依赖
str.size() > 0或str.find("{") != std::string::npos作为前置判断 - 若需兼容非 UTF-8 输入(如 GBK),必须先转码——
iconv或utf8cpp是较轻量的选择,但会增加延迟 - 日志中打印错误时,别直接输出原始字符串(可能含控制字符),建议用
std::quoted(str.substr(0, 50))截断显示
真正的难点不在选哪个库,而在搞清输入来源是否可信、编码是否一致、以及错误反馈是否要区分“格式错”和“编码错”。这两类错误的修复路径完全不同。


















