nlohmann::json 的 is_null() 用法解析:如何判断 JSON 值是否为 null
【免费下载链接】jsonJSON for Modern C++项目地址: https://gitcode.com/GitHub_Trending/js/json
is_null()是 JSON for Modern C++(nlohmann::json)提供的便捷类型检查成员函数之一,用于判断当前 JSON 值是否恰好为null。它在解析可选字段、校验配置文件缺失项、以及遍历异构 JSON 容器等场景中高频使用。读完本文你将掌握is_null()的签名、返回值、异常保证与复杂度特性,并通过源码与测试理解它与value_t类型系统、其他is_*()函数及is_primitive()/is_structured()分类函数之间的关系。
函数签名与基本语义
在nlohmann::json中,is_null()的完整声明如下:
constexpr bool is_null() const noexcept;该函数在且仅在当前 JSON 值为#!json null时返回#!cpp true。它隶属于 basic_json 的“便捷类型检查器”(convenience type checker)一族,同族还包括 is_boolean()、is_array()、is_object()、is_string()、is_number() 等。
返回值
| 当前值类型 | is_null()返回值 |
|---|---|
#!json null | true |
| 其他任意类型(boolean / number / object / array / string / binary 等) | false |
异常安全与复杂度
- 异常安全:
noexcept保证(No-throw guarantee),该成员函数在任何情况下都不会抛出异常,因此可以放心地用于不允许抛出异常的代码路径(例如noexcept函数内部或析构函数中)。 - 复杂度:常数时间(Constant)。整个调用只是一次类型标记的比较,不涉及遍历、分配内存或解析等操作。
从源码看实现原理
is_null()的实现极简,核心是对内部类型标记做一次相等比较。该实现位于 include/nlohmann/json.hpp#L1379-L1384:
/// @brief return whether value is null /// @sa https://json.nlohmann.me/api/basic_json/is_null/ constexpr bool is_null() const noexcept { return m_data.m_type == value_t::null; }其中m_data.m_type是对象内部保存的“当前值类型”标记,其取值来自枚举detail::value_t。该枚举在 include/nlohmann/detail/value_t.hpp#L53-L65 中定义,覆盖了 JSON 的全部十种内部状态:
enum class value_t : std::uint8_t { null, ///< null value object, ///< object (unordered set of name/value pairs) array, ///< array (ordered collection of values) string, ///< string value boolean, ///< boolean value number_integer, ///< number value (signed integer) number_unsigned, ///< number value (unsigned integer) number_float, ///< number value (floating-point) binary, ///< binary array (ordered collection of bytes) discarded ///< discarded by the parser callback function };注意两个易混淆的边界情况:
value_t::discarded不等于value_t::null。discarded仅由解析回调(parser callback)在处理被丢弃的键/值时临时使用,因此一个被标记为discarded的值is_null()也会返回false。nullptr字面量与 C++NULL宏:json(nullptr)构造出的值类型为value_t::null(下文测试用例即用json const j(nullptr)构造空值);但传入 C 风格空指针常量时必须写nullptr,直接写整数0会被当作数字处理而不会得到null值。
由于is_null()声明为constexpr,在编译期可求值的上下文中(例如静态断言或模板元编程)同样可以使用。
它在类型分类体系中的位置
从 include/nlohmann/json.hpp 中相邻的实现可以看出,is_null()不是孤立存在的,它是整套类型分类体系的基础构件:
constexpr bool is_primitive() const noexcept { return is_null() || is_string() || is_boolean() || is_number() || is_binary(); } constexpr bool is_structured() const noexcept { return is_array() || is_object(); }也就是说:
is_primitive()(判断是否为原始类型)会把is_null()的结果作为其真值条件之一:null与字符串、布尔、数字、二进制一起被归为“原始(primitive)”类型,返回true;is_structured()(判断是否为结构化类型)与is_null()完全互补地覆盖数组与对象;is_number()则由is_number_integer() || is_number_float()组合而成,其中整数分支还要进一步区分number_integer与number_unsigned。
相关实现可分别在 include/nlohmann/json.hpp#L1365-L1370(is_primitive)与 include/nlohmann/json.hpp#L1372-L1377(is_structured)中查看。
完整示例:对全部 JSON 类型逐一调用 is_null()
仓库在 docs/mkdocs/docs/examples/is_null.cpp 中提供了一个覆盖所有 JSON 类型的完整示例。该示例创建了包括null、布尔、有符号/无符号整数、浮点数、对象、数组、字符串、二进制在内的九种值,并逐一调用is_null():
#include <iostream> #include <nlohmann/json.hpp> using json = nlohmann::json; int main() { // create JSON values json j_null; json j_boolean = true; json j_number_integer = 17; json j_number_unsigned_integer = 12345678987654321u; json j_number_float = 23.42; json j_object = {{"one", 1}, {"two", 2}}; json j_array = {1, 2, 4, 8, 16}; json j_string = "Hello, world"; json j_binary = json::binary({1, 2, 3}); // call is_null() std::cout << std::boolalpha; std::cout << j_null.is_null() << '\n'; std::cout << j_boolean.is_null() << '\n'; std::cout << j_number_integer.is_null() << '\n'; std::cout << j_number_unsigned_integer.is_null() << '\n'; std::cout << j_number_float.is_null() << '\n'; std::cout << j_object.is_null() << '\n'; std::cout << j_array.is_null() << '\n'; std::cout << j_string.is_null() << '\n'; std::cout << j_binary.is_null() << '\n'; }运行输出(与 docs/mkdocs/docs/examples/is_null.output 一致):
true false false false false false false false false两个值得注意的细节:
- 默认构造
json j_null;得到的正是null值(这也是basic_json默认构造函数的语义),因此它是示例中唯一返回true的对象; - 代码在输出前启用了
std::boolalpha,让布尔结果以true/false而非1/0打印,便于阅读。
单元测试中的验证
类型检查逻辑在测试套件 tests/src/unit-inspection.cpp 的"convenience type checker"一节中得到了系统验证。其测试手法是:为每个 JSON 类型构造一个值,然后用一组CHECK断言逐一确认所有is_*()函数的行为互斥且完备。
以null小节为例(tests/src/unit-inspection.cpp#L58-L74):
SECTION("null") { json const j(nullptr); CHECK(j.is_null()); CHECK(!j.is_boolean()); CHECK(!j.is_number()); CHECK(!j.is_number_integer()); CHECK(!j.is_number_unsigned()); CHECK(!j.is_number_float()); CHECK(!j.is_binary()); CHECK(!j.is_object()); CHECK(!j.is_array()); CHECK(!j.is_string()); CHECK(!j.is_discarded()); CHECK(j.is_primitive()); CHECK(!j.is_structured()); }这里用json const j(nullptr)显式构造空值,随后验证:is_null()为true、其余所有类型判定为false、同时is_primitive()为true而is_structured()为false。对象、数组、布尔等分节的测试(如!j.is_null())则从反方向确认了该判定的排他性。这组测试既是is_null()行为的权威依据,也可以作为读者在自己代码中安全组合各is_*()判定的参考模板。
典型使用场景
结合上述语义,is_null()在真实项目中通常用于以下场合:
- 解析可选字段:当 JSON 对象中某键可能缺失也可能显式为
null时,先用contains()或find()判断键是否存在,再用at(key).is_null()区分“无此键”与“键值为 null”,从而决定是否使用默认值; - 遍历前的安全守卫:对来自第三方接口的嵌套 JSON,在向下取值前先用
is_null()拦截空值,避免对null继续调用get<T>()或下标访问而抛出类型转换/越界异常; - 与
type()配合的精确分支:如果只需要“是否是 null”一个布尔结论,直接使用is_null()即可;若需要穷举所有类型做多路分发,则可以基于 type() 返回的value_t编写switch语句。
需要提醒的是:is_null()只回答“当前值是不是null”这一事实问题,并不会替你决定“null应该当作空值处理还是当作默认值处理”——这层业务逻辑需要调用方在is_null()返回true的分支中自行实现。
版本历史
- 自版本1.0.0起提供(
since version 1.0.0),属于basic_json长久以来保持稳定的核心类型检查接口之一;其底层实现所依赖的value_t枚举同样自 1.0.0 存在。
小结
is_null()是 nlohmann::json 中成本最低、最安全的类型检查接口:常数时间复杂度、noexcept无异常保证、可constexpr求值。它的本质是对内部value_t类型标记的一次相等比较,并与is_primitive()、is_structured()等高层分类函数协同工作。无论是解析可能缺失的 JSON 字段,还是编写遍历异构数据的健壮代码,将is_null()与其他is_*()函数配合使用,都是判断 JSON 值类型最直接、最不易出错的方案。
【免费下载链接】jsonJSON for Modern C++项目地址: https://gitcode.com/GitHub_Trending/js/json
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考