新闻详情

新闻详情

首页 / 资讯中心 / 详情

nlohmann/json update() 详解:C++ 中 JSON 对象的覆盖更新与递归合并

发布时间:2026/9/8 21:05:08来源:尧图网络
nlohmann/json update() 详解:C++ 中 JSON 对象的覆盖更新与递归合并
nlohmann/json update() 详解C 中 JSON 对象的覆盖更新与递归合并【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/jsonupdate()是 nlohmann::basic_json 提供的对象级合并接口对应 Pythondict.update的语义把一个 JSON 对象或迭代器区间中的所有键值对写入当前对象可选择性地对嵌套对象做递归合并。本文基于仓库 API 文档 update.md 及源码实现include/nlohmann/json.hpp、tests/src/unit-modifiers.cpp完整讲解两个重载的签名、merge_objects参数语义、异常行为、复杂度与迭代器失效规则并给出可运行的示例代码和典型配置合并场景。函数签名与核心语义update()有两个重载均定义于nlohmann::basic_jsonjson是它的别名// (1) void update(const_reference j, bool merge_objects false); // (2) void update(const_iterator first, const_iterator last, bool merge_objects false);重载 (1)把 JSON 对象j中的所有键值对插入当前对象重载 (2)把迭代器区间[first, last)中的所有键值对插入当前对象。两者的合并策略由merge_objects控制merge_objects false默认已存在的键直接被覆盖不做任何深度合并merge_objects true双方都存在、且源侧值为对象时对同名键递归合并其余情况照常覆盖。此外还有一个容易被忽视的规则如果当前 JSON 值是null调用update()前它会先被隐式转换为空对象然后才执行插入。这意味着json j; j.update(other);是合法的不需要先j json::object()。文档明确指出该函数设计动机是 Python 的dict.update()习惯 Python 字典合并的开发者可以直接迁移心智模型。merge_objects 参数深度解析merge_objects是update()最有价值的参数也是理解其实现的关键。参数方向说明jin要读取键值对来源的 JSON 对象merge_objectsintrue时双方都存在且源侧值为对象的键会被递归合并其他值一律按覆盖处理。默认falsefirstin待插入元素区间的起点lastin待插入元素区间的终点从源码看include/nlohmann/json.hpp单头文件版本见 single_include/nlohmann/json.hpp核心循环逻辑是for (auto it first; it ! last; it) { if (merge_objects it.value().is_object()) { auto it2 m_data.m_value.object-find(it.key()); // Only recurse when the existing value is itself an object. // Otherwise overwrite, matching the documented all other values // are overwritten as usual behavior (see #5402). if (it2 ! m_data.m_value.object-end() it2-second.is_object()) { it2-second.update(it.value(), true); #if JSON_DIAGNOSTICS it2-second.set_parents(); #endif continue; } } m_data.m_value.object-operator[](it.key()) it.value(); ... }可以确认几个精确的实现细节递归条件是三重的merge_objects为true、源侧值it.value()是对象、且当前对象中该键已存在并且现有值也是对象三者同时满足才递归调用update(..., true)只要有一项不满足就退化为覆盖例如现有值是数组而新值是对象直接整体替换不会报错实现中对「现有值非对象时覆盖」的行为带有明确注释引用了上游 issue #5402说明这是被刻意规范过的语义而非偶然行为开启JSON_DIAGNOSTICS宏后合并过程会同步维护父指针set_parents()用于异常诊断定位。参数校验与异常行为update()按如下顺序做校验同样见 include/nlohmann/json.hpp若当前值为null先隐式转为空对象若当前值不是对象例如 array、string抛出type_error.312消息形如cannot use update() with string重载 (2) 额外校验first与last必须属于同一个JSON 值否则抛出invalid_iterator.210消息为iterators do not fit迭代器指向的对象若不是 object抛出type_error.312。异常安全性为基本保证basic guarantee若操作中途抛出异常JSON 值可能已被部分修改——即合并不是原子的调用方不应假设失败后对象保持原样。单元测试 tests/src/unit-modifiers.cpp 的update()小节对这些分支逐一做了断言例如CHECK_THROWS_WITH_AS(j_array.update(j_object1), [json.exception.type_error.312] cannot use update() with array, json::type_error); CHECK_THROWS_WITH_AS(j_object1.update(j_object1.begin(), j_object2.end()), [json.exception.invalid_iterator.210] iterators do not fit, json::invalid_iterator);这印证了文档中异常表的每一条都有对应回归测试覆盖。复杂度两个重载的时间复杂度相同O(N·log(size() N))其中 N 为待插入元素个数。这与底层对象容器std::map的operator[]写入的对数查找/插入代价一致merge_objects true时递归合并会按子树深度叠加该代价。迭代器失效规则对ordered_json向对象添加值可能触发底层重新分配此时所有迭代器包括end()和所有元素引用全部失效。使用ordered_json调用update()时不要在合并过程中持有迭代器或引用对默认的std::map后端json向对象插入元素通常只失效end()迭代器但建议同样保守处理。示例一两个对象合并覆盖与递归合并的对比以下示例来自 docs/mkdocs/docs/examples/update.cpp#include iostream #include iomanip #include nlohmann/json.hpp using json nlohmann::json; using namespace nlohmann::literals; int main() { // create two JSON objects json o1 R( {color: red, price: 17.99, names: {de: Flugzeug}} )_json; json o2 R( {color: blue, speed: 100, names: {en: plane}} )_json; json o3 o1; // add all keys from o2 to o1 (updating color, replacing names) o1.update(o2); // add all keys from o2 to o1 (updating color, merging names) o3.update(o2, true); // output updated object o1 and o3 std::cout std::setw(2) o1 \n; std::cout std::setw(2) o3 \n; }输出见 docs/mkdocs/docs/examples/update.output{ color: blue, names: { en: plane }, price: 17.99, speed: 100 } { color: blue, names: { de: Flugzeug, en: plane }, price: 17.99, speed: 100 }两段输出的差异正好演示了两种模式o1.update(o2)中names被o2的names整体替换de丢失o3.update(o2, true)中names被递归合并同时保留de与en。示例二使用迭代器区间的重载重载 (2) 允许只合并部分键值对示例见 docs/mkdocs/docs/examples/update__range.cppjson o1 R( {color: red, price: 17.99, names: {de: Flugzeug}} )_json; json o2 R( {color: blue, speed: 100, names: {en: plane}} )_json; json o3 o1; // add all keys from o2 to o1 (updating color, replacing names) o1.update(o2.begin(), o2.end()); // add all keys from o2 to o1 (updating color, merging names) o3.update(o2.begin(), o2.end(), true);行为与示例一完全一致输出见 docs/mkdocs/docs/examples/update__range.output但区间形式让只取部分键成为可能例如o1.update(o2.begin(), std::next(o2.begin(), 2))可以只合并前两个键。注意区间必须来自同一个对象混用两个不同对象的首尾迭代器会触发invalid_iterator.210。实战场景默认配置与用户配置的合并文档给出了一个典型应用场景——用户设置覆盖默认设置。假设应用的可配置项默认值为{ color: red, active: true, name: {de: Maus, en: mouse} }用户只想选择性覆盖其中一部分{ color: blue, name: {es: ratón} }用update完成默认值与用户值的合并auto user_settings json::parse(config.json); auto effective_settings get_default_settings(); effective_settings.update(user_settings);结果中用户设置的键覆盖默认值其余键保留默认{ color: blue, active: true, name: {es: ratón} }注意这里name被整体替换了——用户只给了es默认的de/en丢失。如果需要保留并递归合并嵌套对象把第二个参数设为trueauto user_settings json::parse(config.json); auto effective_settings get_default_settings(); effective_settings.update(user_settings, true);{ color: blue, active: true, name: {de: Maus, en: mouse, es: ratón} }这个模式适用于任何层次化配置 选择性覆盖的场景应用配置、服务网格参数、国际化文案等配合merge_objects true可以在不牺牲默认值的完整性的前提下应用用户补丁。与相关 API 的区分insert向数组/对象插入指定键值或区间已存在的键不会被覆盖语义与update()互补merge_patch按 RFC 7386 语义应用 JSON Merge Patch其中null表示删除键与update()的覆盖语义不同更多对象修改手法参见 Modifying values 专题文档。版本历史update()自3.0.0引入merge_objects参数在3.10.5加入。因此使用递归合并能力时需要确认所用版本不低于 3.10.5。小结update()用两个重载、一个布尔参数覆盖了 JSON 对象合并的两大需求浅层覆盖merge_objects false与递归深合并merge_objects true。使用时需要记住三点null会被隐式转成空对象因此对空值调用是安全的非对象调用会抛type_error.312、混用迭代器会抛invalid_iterator.210失败时对象可能已被部分修改且ordered_json下合并会使全部迭代器失效。对于配置系统这类需要默认值打底、用户值覆盖、嵌套结构保留的场景update(other, true)是目前 nlohmann/json 中最直接的实现手段。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

btop GPU监控完整指南:3 步在终端看全 NVIDIA/AMD/Intel 显卡利用率 2026/9/8 22:17:27

btop GPU监控完整指南:3 步在终端看全 NVIDIA/AMD/Intel 显卡利用率

btop GPU监控完整指南:3 步在终端看全 NVIDIA/AMD/Intel 显卡利用率 【免费下载链接】btop A monitor of resources 项目地址: https://gitcode.com/GitHub_Trending/bt/btop 游戏画面一卡,先别急着猜——盯着 GPU 利用率、显存占用、温度 这三个…

阅读更多 →
three.js 中 SphericalHarmonics3 解析:用 9 个系数编码光照的球谐函数实现 2026/9/8 22:17:27

three.js 中 SphericalHarmonics3 解析:用 9 个系数编码光照的球谐函数实现

three.js 中 SphericalHarmonics3 解析:用 9 个系数编码光照的球谐函数实现 【免费下载链接】three.js JavaScript 3D Library. 项目地址: https://gitcode.com/GitHub_Trending/th/three.js SphericalHarmonics3 是 three.js 中用于表示三阶(L2&…

阅读更多 →
OpenCode 深度指南:终端 AI 编程代理的安装、配置与实战避坑 2026/9/8 22:17:27

OpenCode 深度指南:终端 AI 编程代理的安装、配置与实战避坑

用过 Claude Code 之后,我一度觉得终端里跑 AI 编程代理这事已经被玩明白了。直到我换到 OpenCode,才意识到之前的方案还是太“重”了:要么锁定某一家模型,要么只能在特定 IDE 里用,要么想接自己的私有模型得折腾半天。…

阅读更多 →
Cursor+Codex重构微信小游戏开发工作流 2026/9/8 22:17:27

Cursor+Codex重构微信小游戏开发工作流

1. 这不是“AI写代码”,而是用工具链重构开发节奏的真实记录 “一个人,4个岗位,20天:我用CursorCodex上线了一款微信小游戏”——这句话在技术圈刷屏时,我第一反应是:又一个标题党?直到点开评论…

阅读更多 →
2026微商城平台推荐:真正难的不是开店,是别把客户卖丢 2026/9/8 22:17:27

2026微商城平台推荐:真正难的不是开店,是别把客户卖丢

今天给大家带来2026微商城平台推荐:真正难的不是开店,是别把客户卖丢。腾讯公开信息显示,2025年微信小程序生态已覆盖100个国家和地区、108个行业,跨境交易金额同比增长超过70%;微信小程序目前拥有超过11亿月活跃用户。…

阅读更多 →
基于STM32F103的摄像头循迹小车:从图像处理到PID控制全解析 2026/9/8 22:14:27

基于STM32F103的摄像头循迹小车:从图像处理到PID控制全解析

简介:基于STM32F103的摄像头循迹智能小车系统,面向嵌入式开发学习者和智能车竞赛爱好者,融合OV7670图像采集、二值化道路识别和超声波避障等关键技术,可广泛应用于毕业设计、课程设计与机器人入门实践。压缩包共166个文件&#xf…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞