nlohmann-json basic_json::array 详解:从初始化列表显式构造 JSON 数组 nlohmann-json basic_json::array 详解从初始化列表显式构造 JSON 数组【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json导读在 JSON for Modern Cnlohmann/json中json::array(...)是一个静态工厂函数用于从 C 初始化列表显式创建一个 JSON 数组值nlohmann::basic_json::array。它存在的意义是解决初始化列表构造函数basic_json(initializer_list_t)无法表达的两种边界情况创建空数组和创建元素全为字符串键值对的数组。本文完整讲解该函数的签名、参数、异常安全与复杂度并结合仓库源码剖析其类型判定逻辑与单元测试验证帮助你在需要精确控制 JSON 类型时正确选用它。函数签名与基本语义array的声明如下static basic_json array(initializer_list_t init {});给定一组值a, b, c该函数创建 JSON 值[a, b, c]若初始化列表为空则创建空数组[]。参数initin—— 用于创建数组的 JSON 值初始化列表可选默认为空列表{}返回值一个 JSON 数组类型的basic_json值异常安全强保证strong guarantee——若抛出异常JSON 值不发生变化复杂度与init的大小成线性关系版本历史自 1.0.0 版本引入。在 include/nlohmann/json.hpp 中其实现仅有一行转发/// brief explicitly create an array from an initializer list static basic_json array(initializer_list_t init {}) { return basic_json(init, false, value_t::array); }关键信息在于三个实参把init交给三参初始化列表构造函数type_deduction显式传false禁止类型推断manual_type强制为value_t::array。这正是显式二字的底层含义——跳过推断规则直接按数组类型构造。为什么需要 array()初始化列表构造函数的两个盲区array()这个函数并非冗余设计。按照官方 API 文档 array.md 的 Notes 说明它只用于表达两种无法通过初始化列表构造函数basic_json(initializer_list_t, bool, value_t)实现的边界情况元素全部是首元素为字符串的 pair的数组——如果直接把这种列表交给初始化列表构造函数它会被推断为 object把每个 pair 的第一个元素当作键空数组——把空的初始化列表传给初始化列表构造函数得到的是空对象{}而非空数组[]。这两条规则源自初始化列表构造函数的类型推断策略见 basic_json.md 的重载 5 说明若列表为空创建空 JSON 对象{}因为{}在 C 中天然对应空对象字面量若列表由若干 pair 组成且每个 pair 的首元素是字符串创建 JSON object首元素作键、次元素作值JSON 要求键必须是字符串这是能施加的最弱约束;其他一切情况创建 array。规则的设计意图是让 C 初始化列表与 JSON 值最贴合但代价就是上述两个 JSON 值无法用裸{...}字面量表达。因此array(initializer_list_t)和object(initializer_list_t)作为强制创建的入口被引入。源码级原理类型判定与强制数组从 include/nlohmann/json.hpp 中basic_json(initializer_list_t, bool, value_t)的实现可以看到完整判定链路basic_json(initializer_list_t init, bool type_deduction true, value_t manual_type value_t::array) { // check if each element is an array with two elements whose first // element is a string bool is_an_object std::all_of(init.begin(), init.end(), [](const detail::json_refbasic_json element_ref) { return element_ref-is_array() element_ref-size() 2 (*element_ref)[static_castsize_type(0)].is_string(); }); // adjust type if type deduction is not wanted if (!type_deduction) { // if an array is wanted, do not create an object though possible if (manual_type value_t::array) { is_an_object false; } // if an object is wanted but impossible, throw an exception if (JSON_HEDLEY_UNLIKELY(manual_type value_t::object !is_an_object)) { JSON_THROW(type_error::create(301, cannot create object from initializer list, nullptr)); } } // ... }三个要点值得注意推断条件is_an_object由std::all_of计算——列表中每一个元素都必须是长度为 2 的数组且其第 0 个元素是字符串。任何一个不满足就整体判为数组。源码中还对下标做了static_castsize_type(0)的显式转换注释说明这是为了防止某些string_t类型可以通过0空指针形态构造而误走op[key_type]分支例如在 Windows 上产生 4804 警告。强制数组路径当type_deduction false且manual_type value_t::array即array()的调用路径时直接把is_an_object置为false——即使列表完全符合对象形态也按数组创建。这就是json::array({ {one, 1}, {two, 2} })得到[[one,1],[two,2]]而非{one:1,two:2}的原因。与 object() 的不对称manual_type value_t::object而列表不满足对象形态时抛出type_error.301而强制数组则永远不会抛这类异常。这也是为什么 object.md 文档中说object()仅出于对称性添加而array()有真实的不可替代场景。完整示例与输出以下是官方示例 docs/mkdocs/docs/examples/array.cpp 的完整代码#include iostream #include nlohmann/json.hpp using json nlohmann::json; int main() { // create JSON arrays json j_no_init_list json::array(); json j_empty_init_list json::array({}); json j_nonempty_init_list json::array({1, 2, 3, 4}); json j_list_of_pairs json::array({ {one, 1}, {two, 2} }); // serialize the JSON arrays std::cout j_no_init_list \n; std::cout j_empty_init_list \n; std::cout j_nonempty_init_list \n; std::cout j_list_of_pairs \n; }对应输出见 docs/mkdocs/docs/examples/array.output[] [] [1,2,3,4] [[one,1],[two,2]]逐行对照四个用例表达式结果说明json::array()[]使用默认参数{}得到空数组裸json{}会得到null裸json{}之外的json j{}会得到空对象{}json::array({})[]显式空初始化列表仍是空数组json::array({1, 2, 3, 4})[1,2,3,4]普通元素数组与初始化列表构造函数行为一致json::array({ {one, 1}, {two, 2} })[[one,1],[two,2]]关键用例若交给basic_json(initializer_list_t)此处会得到对象{one:1,two:2}array()强制保留 pair 结构为数组元素最后一行正是盲区 1的直接体现pair 列表没有变成对象而是每个 pair 原样成为数组的一个元素。单元测试验证仓库的单元测试 tests/src/unit-constructor1.cpp 中对json::array有专门的断言用例SECTION(empty array) { json const j json::array(); CHECK(j.type() json::value_t::array); } SECTION(array) { json const j json::array({ {one, 1}, {two, 1u}, {three, 2.2}, {four, false} }); CHECK(j.type() json::value_t::array); }第二个用例特意构造了一个混合型 pair 列表——第二个 pair 的键是1u无符号整数非字符串该列表本就不满足对象推断条件测试确认json::array(...)的返回类型始终为json::value_t::array。结合源码可知即使换成纯字符串键的 pair 列表type_deduction false分支也会强制is_an_object false类型判定结果不变。相关 API 与延伸阅读basic_json(initializer_list_t)—— 从初始化列表创建 JSON 值的构造函数其类型推断规则是理解array()存在前提的关键注意其文档中特别提示花括号初始化json j2{j1}会得到单元素数组[hello]而非拷贝如需单元素数组应显式写json::array({value})object—— 对称的静态工厂强制从初始化列表创建对象与init形态不符时抛type_error.301Creating JSON values —— 关于创建各类 JSON 值的系统性文章array()与object()在该体系中属于显式类型控制工具。使用建议小结想要的值推荐写法空数组[]json::array()普通数组[1,2,3]json::array({1,2,3})或json{1,2,3}均可字符串键 pair 列表构成的数组必须用json::array({ {k, v}, ... })空对象{}json::object()或json::object({})单元素数组避免花括号初始化陷阱json::array({value})从源码结构看array()与object()都只是对三参初始化列表构造函数的薄封装全部复杂度逻辑集中在类型判定函数中因此它们没有额外的性能开销复杂度与直接调用构造函数相同均为初始化列表大小的线性时间。自 1.0.0 起该接口稳定存在在需要精确控制 JSON 值类型的场景如构造 JSON Patch、序列化嵌套二元组数据中可以放心使用。【免费下载链接】jsonJSON for Modern C项目地址: https://gitcode.com/GitHub_Trending/js/json创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考