ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

JSON for Modern C++ 中 basic_json::count 接口详解:键计数查询、透明比较约束与源码实现

JSON for Modern C++ 中 basic_json::count 接口详解:键计数查询、透明比较约束与源码实现 JSON for Modern C 中 basic_json::count 接口详解键计数查询、透明比较约束与源码实现【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json本文围绕 nlohmann::basic_json::count 这一 API 参考文档展开系统讲解 JSON for Modern Cnlohmann/json中count()方法两个重载的声明、参数、返回值与版本历史并结合仓库源码include/nlohmann/json.hpp与单元测试tests/src/unit-element_access2.cpp深入剖析其类型约束、透明比较器transparent comparator机制以及“非对象类型一律返回 0”的行为保证帮助读者在 C 项目中安全、高效地判断 JSON 对象中键的重复/存在情况。一、接口总览count() 的两种声明官方 API 文档给出的完整声明如下// (1) size_type count(const typename object_t::key_type key) const; // (2) templatetypename KeyType size_type count(KeyType key) const;重载 (1)以标准键类型object_t::key_type默认std::string的 const 引用接收键。当ObjectType为默认的std::map类型时返回值恒为0键未找到或1键找到因为std::map的键天然唯一。重载 (2)模板重载接受任意可转发的KeyType key。其可用性有前提条件KeyType必须能通过object_comparator_t与typename object_t::key_type比较且typename object_comparator_t::is_transparent必须是一个合法类型即比较器支持透明比较。这也是为什么该重载可以从 C17 起接受std::string_view的原因。项目说明参数key(in)要统计的元素的键值返回值键为key的元素个数若 JSON 值不是对象返回值恒为0异常安全性强异常安全strong exception safety若发生异常原值保持不变时间复杂度与 JSON 对象规模成对数关系logarithmic模板参数KeyType除 json_pointer 外任何可与 string_t 通过 object_comparator_t 比较的键类型C17 下可以是 string view注意事项Notes对任何非 object 类型的 JSON 值null、数组、数值、字符串、布尔等执行count()结果总是0不会抛出异常。这使得count()可以作为“存在性检查”的安全入口无需先判断值类型。二、重载 (1) 实战用标准键计数官方示例完整源码见 count__object_t_key_type.cpp展示了最典型的用法#include iostream #include nlohmann/json.hpp using json nlohmann::json; int main() { // create a JSON object json j_object {{one, 1}, {two, 2}}; // call count() auto count_two j_object.count(two); auto count_three j_object.count(three); // print values std::cout number of elements with key \two\: count_two \n; std::cout number of elements with key \three\: count_three \n; }运行输出见 count__object_t_key_type.outputnumber of elements with key two: 1 number of elements with key three: 0源码实现一行三元表达式从源码结构看重载 (1) 的实现极其简洁include/nlohmann/json.hpp/// brief returns the number of occurrences of a key in a JSON object size_type count(const typename object_t::key_type key) const { // return 0 for all nonobject types return is_object() ? m_data.m_value.object-count(key) : 0; }其逻辑分两步先调用is_object()做类型门控——非对象类型直接短路返回0这正是文档 Notes 一节“非对象恒返回 0”承诺的实现来源也是其异常安全与无异常特性的来源之一若确为对象则把调用原样转发给底层m_data.m_value.object默认即std::mapstring_t, basic_json的count成员因此复杂度继承自底层容器的 O(log n)与文档“Logarithmic in the size of the JSON object”的描述一致。单元测试 tests/src/unit-element_access2.cpp 中的count keys in an object分区约 L1199-L1245对该行为做了穷举验证已存在键对对象中全部 8 种值类型键integer、unsigned、floating、null、string、boolean、object、array逐一断言j.count(key) 1const 版本同样成立不存在键断言j.count(foo) 0所有非对象类型null、string、各类 number、boolean、array 等分别断言count(foo) 0覆盖了文档“非对象返回 0”的全部类型分支。三、重载 (2) 实战透明比较与 string_viewC17第二个重载允许传入std::string、const char*乃至 C17 的std::string_view等非string_t键类型避免为一次查询构造临时std::string。官方 C17 示例完整源码见 count__keytype.c17.cpp#include iostream #include string_view #include nlohmann/json.hpp using namespace std::string_view_literals; using json nlohmann::json; int main() { // create a JSON object json j_object {{one, 1}, {two, 2}}; // call count() auto count_two j_object.count(twosv); auto count_three j_object.count(threesv); // print values std::cout number of elements with key \two\: count_two \n; std::cout number of elements with key \three\: count_three \n; }输出count__keytype.c17.outputnumber of elements with key two: 1 number of elements with key three: 0类型约束的源码剖析该重载的 SFINAE 约束直接写在函数签名上include/nlohmann/json.hpptemplateclass KeyType, detail::enable_if_t detail::is_usable_as_basic_json_key_typebasic_json_t, KeyType::value, int 0 size_type count(KeyType key) const { // return 0 for all nonobject types return is_object() ? m_data.m_value.object-count(std::forwardKeyType(key)) : 0; }关键有两点std::forwardKeyType(key)完美转发键以原样引用类别保持不变转发给底层对象容器的count配合透明比较器可避免多余的字符串拷贝is_usable_as_basic_json_key_type类型特征决定了哪些KeyType能通过编译。该特征定义于 include/nlohmann/detail/meta/type_traits.hpp从源码结构看判定true需要同时满足KeyType可通过object_comparator_t与BasicJsonType::object_t::key_type比较KeyType不恰好是object_t::key_type本身后者由重载 (1) 负责避免歧义比较器具备is_transparent类型默认std::less满足此条件KeyType不是json_pointer、不是 JSON 迭代器C17 下额外放宽任何可转换为std::string_view的类型也直接放行std::is_convertibleKeyType, std::string_view这正是count(twosv)得以编译的直接原因。因此文档中“KeyType是除json_pointer外、可与string_t比较的键类型且 C17 下可以是 string view”的模板参数说明与源码约束一一对应。若传入不满足约束的类型例如整数编译期即会因enable_if_t失配而报错属于编译期防护而非运行期行为。四、与 find / contains 的关系与选型API 文档的 See also 一节将count()与以下两个接口关联find在对象中查找值返回迭代器可继续取值contains判断键是否存在返回bool。三者共用同一套“非对象返回空/假”的安全语义且都受同一透明比较约束contains的模板重载同样使用is_usable_as_basic_json_key_type见 include/nlohmann/json.hpp。选型上可以这样理解只需要判断“有没有”contains(key) (count(key) 0)contains语义更直白需要同时拿到“存在性 对应值”时find一次调用即可避免countoperator[]的两次查找count的独特价值在于与标准库std::map::count语义对齐对唯一键容器它就是0/1指示器但在自定义ObjectType如nlohmann::ordered_map之外的多键容器场景下语义保持通用。仓库测试 tests/src/unit-ordered_map.cpp 的count分区也验证了ordered_map对字面量、临时std::string、具名变量三种键形式的count行为一致存在为 1、不存在为 0。五、版本历史与适用前提根据 API 文档的 Version history 一节重载 (1)自版本3.11.0起提供重载 (2)自版本1.0.0起提供且在版本3.11.0将参数key的类型变更为KeyType改为完美转发形式。适用前提小结需要#include nlohmann/json.hpp单头文件版见 single_include/nlohmann/json.hppC11 起可用std::string_view用法需要 C17 编译标准且要求比较器支持透明比较默认比较器满足两个重载均为const成员可在 const 对象上安全调用若项目关闭了异常支持count()的非对象返回 0 语义依然成立因为它不依赖抛出异常的路径。小结basic_json::count()是 JSON for Modern C 中与标准库容器语义对齐的键查询接口重载 (1) 以object_t::key_type计数重载 (2) 借助is_usable_as_basic_json_key_type约束与透明比较器支持string_view等零拷贝键两者都以is_object()门控保证非对象类型恒返回 0、强异常安全复杂度 O(log n)。其实现集中在 include/nlohmann/json.hpp类型约束在 include/nlohmann/detail/meta/type_traits.hpp行为验证覆盖于 tests/src/unit-element_access2.cpp 与 tests/src/unit-ordered_map.cpp可作为查阅与回归测试的起点。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表