ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

nlohmann::basic_json::other_error 异常详解:5xx 错误码定位与处理实战

nlohmann::basic_json::other_error 异常详解:5xx 错误码定位与处理实战 nlohmann::basic_json::other_error 异常详解5xx 错误码定位与处理实战【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json本篇文章基于 JSON for Modern Cnlohmann/json仓库的官方 API 文档系统讲解nlohmann::basic_json::other_error异常类——它用于承载无法归入解析、迭代器、类型、越界等既有类别的“其它库错误”异常 id 统一为 5xx。读完本文你将掌握它的类层次定位、成员接口、两条实际错误501/502的触发场景与源码依据并能在真实项目中准确捕获与诊断这类异常。一、定位other_error在异常体系中的位置在 nlohmann/json 中basic_json抛出的所有异常都继承自basic_json::exception它又继承自std::exception。库把错误按语义划分成五大分支other_error正是其中承接“无法归入其它类别”的兜底分支官方声明如下class other_error : public exception;从 home/exceptions.md 与 exception.md 的类图可以看到完整层级std::exception └── basic_json::exception 拥有 const int id 与 what() ├── basic_json::parse_error id 1xx解析错误 ├── basic_json::invalid_iterator id 2xx迭代器语义错误 ├── basic_json::type_error id 3xx在错误类型上执行操作 ├── basic_json::out_of_range id 4xx越界访问 └── basic_json::other_error id 5xx其它库错误other_error与兄弟异常类共享同一个 5xx 编号体系错误消息格式统一为[json.exception.other_error.id] 说明。该异常自版本 3.0.0 起提供见文档 other_error.md 的 Version history。二、源码视角类的成员与消息构造other_error的实现位于 include/nlohmann/detail/exceptions.hpp其接口非常简单成员函数what()返回可读的错误说明字符串继承自exception内部经std::runtime_error存储noexcept覆盖成员变量id异常数字编号const int用于程序化区分错误类型。该类提供静态工厂create(id_, what_arg, context)底层异常消息的构造逻辑见 exceptions.hpp会把类型名与 id 拼接成规范前缀static std::string name(const std::string ename, int id_) { return concat([json.exception., ename, ., std::to_string(id_), ] ); }第三个参数context是诊断上下文当启用JSON_DIAGNOSTICS时库会把触发错误的 JSON 值在整棵文档中的路径JSON Pointer附加进消息未启用时该前缀为空。这意味着同样一个 501 错误开启扩展诊断后会额外携带类似(/0)的定位信息——这一点在后面的测试用例中可以直接看到。另外从代码结构看exception内部使用std::runtime_error承载任意长度错误消息并保证异常“no-throw 可拷贝”exceptions.hpp因此在异常被跨函数、跨线程传递时是安全高效的。三、other_error 的抛出点5xx 都发生在哪里全仓库范围内调用other_error::create的位置非常有限且集中可以逐一检索确认本文只详细展开文档明确记录的两类。3.1 id 501JSON Patchtest操作失败RFC 6902 JSON Patch 的test操作断言失败时抛出 501这是 5xx 中最常见的场景。其语义是test要求目标路径上的现有值与补丁中给定的value完全相等不相等即视为失败。实现位置在 include/nlohmann/json.hpp库先尝试比较result.at(ptr) get_value(test, value, false)如果比较结果为假则抛出 501 并把整条未成功的操作原样打印出来JSON_THROW(other_error::create(501, detail::concat(unsuccessful: , val.dump()), val));于是错误消息形如[json.exception.other_error.501] unsuccessful: {op:test,path:/best_biscuit/name,value:Choco Leibniz}注意path不存在的场景不会被 501 覆盖此时at()抛出的out_of_range会被内部捕获并吞掉success保持false最终仍然抛出 501——也就是说“路径不存在”与“值不相等”对调用者而言统一表现为一次test断言失败json.hpp。官方文档在 home/exceptions.md 中给出的示例对{baz: qux}执行{op:test,path:/baz,value:bar}抛出[json.exception.other_error.501] unsuccessful: {op:test,path:/baz,value:bar}该行为在测试 tests/src/unit-json_patch.cpp 中有完整断言doc.patch(patch)抛出json::other_error且消息中包含unsuccessful:与补丁操作本身开启JSON_DIAGNOSTICS时消息会多出/0或字节区间bytes 47-95前缀恰好印证了前文 context 拼接的机制。3.2 id 502UBJSON/BJData 序列化参数矛盾to_ubjson与to_bjdata被以use_type true但use_size false的组合调用时抛出 502。UBJSON/BJData 规范要求类型标记$之后必须紧跟尺寸标记#二者必须成对出现因此这种参数组合无法产出合法字节流。实现位于二进制序列化器 include/nlohmann/detail/output/binary_writer.hpp错误消息固定为[json.exception.other_error.502] use_type requires use_size true对应测试见 tests/src/unit-ubjson.cpp 与 tests/src/unit-bjdata.cpp对非空数组/对象调用to_ubjson(j, true, false)或 BJData 等价调用会抛出带该文本的json::other_error。四、完整可运行示例捕获 other_error官方示例 examples/other_error.cpp 演示了如何让一次 JSON Patchtest操作失败并捕获 501#include iostream #include nlohmann/json.hpp using json nlohmann::json; using namespace nlohmann::literals; int main() { try { // executing a failing JSON Patch operation json value R({ best_biscuit: { name: Oreo } })_json; json patch R([{ op: test, path: /best_biscuit/name, value: Choco Leibniz }])_json; value.patch(patch); } catch (const json::other_error e) { // output exception information std::cout message: e.what() \n exception id: e.id std::endl; } }示例真实输出见 examples/other_error.outputmessage: [json.exception.other_error.501] unsuccessful: {op:test,path:/best_biscuit/name,value:Choco Leibniz} exception id: 501value中best_biscuit.name的值为Oreo而补丁要求其等于Choco Leibniz二者不等test断言失败异常被catch (const json::other_error e)接住——e.what()提供完整说明e.id为 501。这段代码可以直接编译运行前提是工程能 include 到仓库的 single_include/nlohmann/json.hpp 单头文件或 include/nlohmann/json.hpp。五、捕获策略与异常开关由于所有异常共享基类exception实际编码时有三种粒度可选精确捕获catch (const json::other_error e)——只处理 5xx分组捕获分别 catchparse_error/invalid_iterator/type_error/out_of_range/other_error按 1xx~5xx 分类响应通配捕获catch (const json::exception e)——一次性捕获库抛出的全部异常exception.md。另外该库支持通过编译器选项-fno-exceptions或定义宏JSON_NOEXCEPTION整体关闭异常此时所有异常抛出点被替换为abort()调用。若需要更细的控制可用JSON_THROW_USER、JSON_TRY_USER、JSON_CATCH_USER三个宏分别覆盖throw/try/catch——例如官方文档演示了把错误日志写入std::clog后再abort()的做法。注意JSON_THROW_USER宏体必须以抛出或中止方式离开当前作用域否则继续执行属于未定义行为见 home/exceptions.md。在关闭异常的场景下what()消息在 MSVC 上不可用home/exceptions.md 中的已知说明。六、提升可诊断性JSON_DIAGNOSTICS 扩展上下文默认情况下异常只在“出事的那一层 JSON 值”的局部上下文抛出调试时往往难以定位深嵌套文档中具体是哪个路径出了问题。为此库提供了JSON_DIAGNOSTICS宏定义后再抛出的异常会把从根到出错值的JSON Pointer 路径织入消息。以 501 为例tests/src/unit-json_patch.cpp 验证了开启后消息会带上前缀(/0)0 号补丁操作同时若再配合字节位置诊断还可能呈现(bytes 47-95)这样的区间标记。其路径回溯逻辑实现在 exceptions.hpp借助每个 JSON 值持有的父指针沿树向上逐层收集 key/下标最终拼出标准 JSON Pointer。代价是每个 JSON 值需要额外存储一个父指针并在运行时维护父子关系因此该特性默认关闭。详见宏文档JSON_DIAGNOSTICS与 home/exceptions.md 的 “Extended diagnostic messages” 一节。七、关联阅读与小结other_error并非孤立设计它与整套异常分类配套使用解析类问题归parse_error1xx迭代器用法错误归invalid_iterator2xx在错误类型上执行成员函数归type_error3xx越界访问归out_of_range4xx无法归类的库错误归other_error5xx从实战角度看遇到[json.exception.other_error.xxx]消息时按 id 决策即可501 意味着 JSON Patchtest断言失败应核对补丁path处的实际值与value是否一致路径可能根本不存在502 意味着向to_ubjson/to_bjdata传入了use_typetrue, use_sizefalse的非法组合应将use_size同步置为true。需要从源码进一步佐证时可重点查看 exceptions.hpp、json.hpp、binary_writer.hpp 三处实现以及 unit-json_patch.cpp、unit-ubjson.cpp、unit-bjdata.cpp 对应的回归测试。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表