nlohmann json lib

nlohmann json Modern C++ JSON lib

摘要

本文档全面介绍了 nlohmann/json,一个广受欢迎的现代C++ JSON库。我们将从其起源与发展入手,探讨其在C++生态系统中的地位,并与其他主流C++ JSON库进行比较。随后,深入剖析 nlohmann/json 的架构与设计哲学,揭示其简洁易用的特点。最后,文档将详细阐述 nlohmann/json 在C++项目中的具体应用,包括安装、基本语法、核心API以及高级用法,旨在为C++开发者提供一份权威、实用的参考指南。

关键词: C++, JSON, nlohmann/json, 数据序列化, 反序列化, 开源库


1. nlohmann/json 简介

1.1 nlohmann的起源与发展

nlohmann/json 库由Niels Lohmann于2013年启动开发,其设计初衷是为C++提供一个现代、直观且功能完备的JSON处理解决方案。在JSON成为Web应用和数据交换事实标准的背景下,C++社区对一个易于使用且性能良好的JSON库的需求日益增长。早期的C++ JSON库往往存在API复杂、学习曲线陡峭或依赖外部库过多的问题。nlohmann/json 的出现,以其仅头文件无需编译API设计与标准库容器(如 std::vectorstd::map)高度契合的特点,迅速获得了C++开发者的青睐。

自发布以来,nlohmann/json 持续迭代,不断完善功能、提升性能并修复潜在问题。它在GitHub上拥有庞大的社区支持和活跃的开发,已成为C++生态系统中处理JSON数据的首选库之一,广泛应用于各种项目,包括嵌入式系统、高性能服务器、桌面应用等。

1.2 与其他C++ JSON库的比较

C++社区拥有多种JSON处理库,各有优劣。下表对 nlohmann/json 与其他几个主流C++ JSON库进行了比较:

特性/库 nlohmann/json RapidJSON Boost.PropertyTree jsoncpp
API设计 直观,类似STL容器操作 DOM/SAX,性能导向 树形结构,通用数据 DOM,传统C++风格
易用性 极高,学习曲线平缓 中等,需要理解DOM/SAX模型 中等,需要理解属性树概念 中等,较为传统
性能 良好,满足大多数应用 极高,注重解析和序列化速度 中等,通用性带来的开销 中等
依赖 仅头文件,无外部依赖 仅头文件,无外部依赖 Boost库,依赖较重 需编译,无外部依赖
功能完备性 完备,支持各种JSON操作 完备,支持各种JSON操作 完备,但JSON仅是其一种格式 完备
内存效率 良好,但可能不如RapidJSON极致 极高,池分配器优化 中等 中等
编译时间 快速(仅头文件) 快速(仅头文件) 较慢(Boost库) 较慢(需编译)

总结:

  • nlohmann/json: 适用于追求开发效率、代码简洁性和易用性的项目。其API设计哲学使得C++开发者能够以自然的方式操作JSON数据。
  • RapidJSON: 适用于对性能有极致要求的场景,如大数据处理、高并发服务器等。但其API相对底层,学习成本较高。
  • Boost.PropertyTree: 提供更通用的树状数据结构处理能力,JSON只是其支持的一种序列化格式。适用于需要处理多种配置或数据格式的复杂系统。
  • jsoncpp: 一个成熟但相对传统的C++ JSON库,其API风格可能不如 nlohmann/json 现代和直观。

1.3 nlohmann的架构与设计理念

nlohmann/json 的核心设计理念是**“像使用标准库容器一样使用JSON”**。它通过重载运算符和提供类似STL的接口,使得JSON对象的创建、访问和修改变得异常直观。

其架构主要基于一个 basic_json 模板类,该类可以根据需要进行特化,以支持不同类型和自定义的分配器。默认的 json 类型是 basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double, std::allocator> 的别名,它代表了JSON数据模型中的六种基本类型:null、布尔值、数字(整数和浮点数)、字符串、数组和对象。

设计原则:

  • 仅头文件 (Header-Only): nlohmann/json 仅由一个头文件 (json.hpp) 组成,无需编译即可直接包含到项目中,极大地简化了集成过程。
  • 强类型安全 (Strong Type Safety): 尽管JSON本身是无模式的,但 nlohmann/json 在运行时提供了类型检查机制。尝试以错误类型访问JSON值会抛出异常,有助于在开发阶段发现问题。
  • 直观的API: 借鉴C++标准库的设计思想,通过重载 operator[]operator=push_back 等,使得JSON操作与C++容器操作保持一致性。
  • 异常安全 (Exception Safety): 库在发生错误时(如类型不匹配、键不存在等)会抛出 json::exception 或其派生类,允许开发者使用 try-catch 机制进行错误处理。
  • 透明的序列化/反序列化 (Transparent Serialization/Deserialization): 通过集成 operator<<operator>>,使得JSON数据的I/O操作与C++流操作无缝衔接。
  • 支持自定义类型 (Support for Custom Types): 提供了 to_jsonfrom_json 机制,允许开发者轻松地将自定义C++对象序列化为JSON,以及将JSON反序列化为自定义对象。
  • C++11及更高版本兼容: 充分利用C++11及后续标准的新特性,如右值引用、auto 关键字、列表初始化等,使得代码更加现代和高效。

2. nlohmann在C++中的应用

2.1 nlohmann的安装与引用

由于 nlohmann/json 是一个仅头文件的库,其安装和引用过程非常简单。

2.1.1 安装

手动下载

直接从GitHub仓库下载最新的 json.hpp 文件:https://github.com/nlohmann/json/releases

将其放置在您的C++项目可以找到的某个包含路径下。

CMake

如果您的项目使用CMake,可以通过 FetchContent 或 add_subdirectory 来集成。

使用 FetchContent (推荐):

include(FetchContent)
FetchContent_Declare(
	nlohmann_json
	GIT_REPOSITORY https://github.com/nlohmann/json.git
	GIT_TAG        v3.11.2 # 或其他最新版本
)
FetchContent_MakeAvailable(nlohmann_json)

# 在您的目标中链接
target_link_libraries(YourProject PRIVATE nlohmann_json::nlohmann_json)
包管理器
  • Conan: 在 conanfile.txtconanfile.py 中添加 nlohmann_json/x.y.z
  • vcpkg: vcpkg install nlohmann-json
  • Homebrew (macOS/Linux): brew install nlohmann-json

2.1.2 引用

在C++源文件中,只需简单地包含 json.hpp 头文件即可:

#include <iostream>
#include "json.hpp" // 如果json.hpp在项目根目录或指定包含路径下
// 或者 #include <nlohmann/json.hpp> 如果通过CMake或包管理器安装

为了方便使用 nlohmann::json 类型,通常会使用 using 声明:

using json = nlohmann::json;

2.2 基本语法

nlohmann/json 提供了与C++标准库容器相似的直观API,使得JSON数据的操作变得非常自然。

2.2.1 JSON对象的创建与初始化

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    // 1. 空JSON对象
    json j_empty_object = json::object();
    json j_empty_object_alt = {}; // 使用列表初始化创建空对象

    // 2. 空JSON数组
    json j_empty_array = json::array();
    json j_empty_array_alt = json::parse("[]"); // 从字符串解析空数组

    // 3. 直接初始化JSON对象
    json j_object = {
        {"name", "Alice"},
        {"age", 30},
        {"isStudent", false},
        {"courses", {"Math", "Physics", "Chemistry"}},
        {"address", {
            {"street", "123 Main St"},
            {"city", "Anytown"}
        }}
    };
    std::cout << "Initialized JSON Object:\n" << j_object.dump(4) << std::endl;

    // 4. 直接初始化JSON数组
    json j_array = {"apple", 123, true, 3.14, nullptr};
    std::cout << "\nInitialized JSON Array:\n" << j_array.dump(4) << std::endl;

    return 0;
}

2.2.2 访问JSON元素

  • 通过键名访问 (对象): 使用 operator[]at()at() 在键不存在时会抛出异常,而 operator[] 会创建新键。
  • 通过索引访问 (数组): 使用 operator[]at()
  • 类型检查: is_string(), is_number(), is_boolean(), is_array(), is_object(), is_null()
  • 类型转换: 使用 get<T>() 或隐式转换。
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json data = {
        {"name", "Bob"},
        {"age", 25},
        {"city", "New York"},
        {"interests", {"coding", "reading", "hiking"}},
        {"details", {
            {"is_active", true},
            {"member_since", 2020}
        }},
        {"null_value", nullptr}
    };

    // 访问对象元素
    std::cout << "Name: " << data["name"] << std::endl; // Bob
    std::cout << "Age: " << data.at("age") << std::endl; // 25

    // 访问数组元素
    std::cout << "First interest: " << data["interests"][0] << std::endl; // coding
    std::cout << "Second interest (using at()): " << data.at("interests").at(1) << std::endl; // reading

    // 访问嵌套元素
    std::cout << "Is active: " << data["details"]["is_active"] << std::endl; // true

    // 类型检查
    if (data["age"].is_number()) {
        std::cout << "Age is a number." << std::endl;
    }
    if (data["interests"].is_array()) {
        std::cout << "Interests is an array." << std::endl;
    }
    if (data["null_value"].is_null()) {
        std::cout << "Null value is null." << std::endl;
    }

    // 类型转换
    std::string name = data["name"].get<std::string>();
    int age = data["age"]; // 隐式转换
    bool isActive = data["details"]["is_active"];

    std::cout << "Name (converted): " << name << std::endl;
    std::cout << "Age (converted): " << age << std::endl;
    std::cout << "Is active (converted): " << isActive << std::endl;

    // 访问不存在的键 (operator[] 会创建,at() 会抛异常)
    std::cout << "Trying to access non-existent key (operator[]): " << data["non_existent_key"] << std::endl;
    // std::cout << data.at("another_non_existent_key") << std::endl; // 这会抛出 json::out_of_range 异常

    return 0;
}

2.2.3 修改JSON元素

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json profile = {
        {"name", "Charlie"},
        {"age", 28},
        {"email", "charlie@example.com"}
    };

    std::cout << "Original profile:\n" << profile.dump(4) << std::endl;

    // 修改现有值
    profile["age"] = 29;
    profile["email"] = "charlie.new@example.com";

    // 添加新键值对
    profile["occupation"] = "Software Engineer";

    // 添加新数组元素
    profile["skills"] = {"C++", "Python", "JavaScript"};
    profile["skills"].push_back("Go");

    // 修改嵌套对象
    profile["address"] = {
        {"street", "456 Oak Ave"},
        {"zip", "10001"}
    };
    profile["address"]["city"] = "San Francisco";

    std::cout << "\nModified profile:\n" << profile.dump(4) << std::endl;

    return 0;
}

2.2.4 遍历JSON

nlohmann/json 支持基于范围的 for 循环遍历JSON对象和数组。

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json data = {
        {"id", 101},
        {"title", "Sample Document"},
        {"tags", {"programming", "json", "c++"}},
        {"contributors", {
            {"name", "Alice"}, {"id", 1}
        }},
        {"contributors", {
            {"name", "Bob"}, {"id", 2}
        }}
    };

    std::cout << "Iterating over JSON object (key-value pairs):\n";
    for (json::iterator it = data.begin(); it != data.end(); ++it) {
        std::cout << "  Key: " << it.key() << ", Value: " << it.value() << std::endl;
    }
    // 或者使用基于范围的 for 循环 (更简洁)
    // for (auto const& [key, val] : data.items()) { // C++17 结构化绑定
    //     std::cout << "  Key: " << key << ", Value: " << val << std::endl;
    // }

    std::cout << "\nIterating over JSON array (tags):\n";
    for (const auto& tag : data["tags"]) {
        std::cout << "  Tag: " << tag << std::endl;
    }

    std::cout << "\nIterating over array of objects (contributors):\n";
    // 注意:如果"contributors"是对象,则第二次赋值会覆盖第一次。
    // 这里假设它是一个数组,演示迭代数组中的对象
    // 重新构建data,确保contributors是数组
    json actual_data = {
        {"id", 101},
        {"title", "Sample Document"},
        {"tags", {"programming", "json", "c++"}},
        {"contributors", json::array({
            {{"name", "Alice"}, {"id", 1}},
            {{"name", "Bob"}, {"id", 2}}
        })}
    };

    for (const auto& contributor : actual_data["contributors"]) {
        std::cout << "  Contributor Name: " << contributor["name"]
                  << ", ID: " << contributor["id"] << std::endl;
    }

    return 0;
}

2.3 核心 API

nlohmann/json 提供了丰富的核心API,用于JSON数据的解析、序列化、查询、操作和类型转换。

2.3.1 解析与序列化

  • 解析 (Parsing): 从字符串、文件流等解析JSON数据。
    • json::parse(source): 从字符串或输入流解析。
    • json::accept(source): 检查字符串是否是有效的JSON而无需完整解析。
  • 序列化 (Serialization): 将JSON数据转换为字符串。
    • dump(indent = -1, indent_char = ' ', ensure_ascii = false): 将JSON序列化为字符串。indent 参数用于美化输出,-1 表示不美化。
#include <iostream>
#include <fstream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    // 从字符串解析
    std::string json_str = R"({"product": "Laptop", "price": 1200.50, "inStock": true})";
    json product_data = json::parse(json_str);
    std::cout << "Parsed from string:\n" << product_data.dump(4) << std::endl;

    // 从文件解析
    // 假设存在一个名为 "config.json" 的文件
    // {"setting1": "value1", "setting2": 123}
    std::ofstream ofs("config.json");
    ofs << R"({"setting1": "value1", "setting2": 123})";
    ofs.close();

    std::ifstream ifs("config.json");
    if (ifs.is_open()) {
        json config;
        ifs >> config; // 使用运算符重载进行解析
        std::cout << "\nParsed from file:\n" << config.dump(4) << std::endl;
        ifs.close();
    } else {
        std::cerr << "Error: Could not open config.json" << std::endl;
    }

    // 序列化为字符串 (美化输出)
    std::string pretty_json = product_data.dump(2); // 2个空格缩进
    std::cout << "\nPretty JSON:\n" << pretty_json << std::endl;

    // 序列化为紧凑字符串 (无缩进)
    std::string compact_json = product_data.dump(); // 默认无缩进 (indent = -1)
    std::cout << "\nCompact JSON:\n" << compact_json << std::endl;

    return 0;
}

2.3.2 查找与查询

  • count(key): 检查JSON对象中是否存在某个键。
  • contains(key): 检查JSON对象中是否存在某个键 (C++20)。
  • find(key): 返回指向键值对的迭代器,如果不存在则返回 end()
  • value(key, default_value): 安全地获取某个键的值,如果键不存在则返回默认值。
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json user = {
        {"id", 1001},
        {"username", "johndoe"},
        {"email", "john@example.com"},
        {"roles", {"admin", "editor"}}
    };

    // 检查键是否存在
    if (user.count("username")) {
        std::cout << "Username exists: " << user["username"] << std::endl;
    }

    if (user.contains("email")) { // C++20 及以上版本可用
        std::cout << "Email exists: " << user["email"] << std::endl;
    }

    // 使用 find()
    auto it = user.find("roles");
    if (it != user.end()) {
        std::cout << "Roles found: " << *it << std::endl;
    } else {
        std::cout << "Roles not found." << std::endl;
    }

    auto non_existent_it = user.find("password");
    if (non_existent_it == user.end()) {
        std::cout << "Password not found (as expected)." << std::endl;
    }

    // 使用 value() 安全获取
    std::string city = user.value("city", "Unknown"); // city不存在,返回"Unknown"
    std::cout << "User's city: " << city << std::endl;

    std::string username = user.value("username", "Guest"); // username存在,返回实际值
    std::cout << "User's username: " << username << std::endl;

    return 0;
}

2.3.3 修改与删除

  • clear(): 清空JSON对象或数组。
  • erase(): 删除元素。
  • push_back(): 向数组添加元素。
  • emplace(): 在对象中插入元素。
  • update(): 合并或更新JSON对象。
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json settings = {
        {"theme", "dark"},
        {"fontSize", 14},
        {"notifications", true},
        {"features", {"darkMode", "autoSave"}}
    };
    std::cout << "Original settings:\n" << settings.dump(4) << std::endl;

    // 修改值
    settings["fontSize"] = 16;

    // 添加新键值对
    settings["language"] = "en-US";

    // 删除键值对
    settings.erase("notifications"); // 按键删除
    // 或者 settings.erase(settings.find("notifications")); // 按迭代器删除

    // 向数组添加元素
    settings["features"].push_back("spellCheck");
    settings["features"].insert(settings["features"].begin(), "hotReload"); // 插入到开头

    // 清空数组
    // settings["features"].clear();

    std::cout << "\nModified settings:\n" << settings.dump(4) << std::endl;

    // update() 合并对象
    json new_defaults = {
        {"language", "zh-CN"}, // 会覆盖
        {"defaultFolder", "/home/user/docs"}, // 会添加
        {"fontSize", 12} // 会覆盖
    };
    settings.update(new_defaults);
    std::cout << "\nSettings after update:\n" << settings.dump(4) << std::endl;

    return 0;
}

2.4 高级语法

2.4.1 自定义类型序列化与反序列化

nlohmann/json 提供了强大的机制,允许开发者轻松地将自定义C++结构体或类与JSON数据进行双向转换,无需手动编写复杂的解析和构建逻辑。这通过为自定义类型重载 to_jsonfrom_json 函数来实现。

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

// 定义一个自定义结构体
struct Person {
    std::string name;
    int age;
    std::vector<std::string> hobbies;
    bool is_student;
};

// 为 Person 类型提供 to_json 函数(将 Person 转换为 json)
void to_json(json& j, const Person& p) {
    j = json{{"name", p.name},
             {"age", p.age},
             {"hobbies", p.hobbies},
             {"is_student", p.is_student}};
}

// 为 Person 类型提供 from_json 函数(将 json 转换为 Person)
void from_json(const json& j, Person& p) {
    j.at("name").get_to(p.name);
    j.at("age").get_to(p.age);
    j.at("hobbies").get_to(p.hobbies);
    j.at("is_student").get_to(p.is_student);
}

int main() {
    // 1. 将 C++ 对象序列化为 JSON
    Person alice = {"Alice", 25, {"reading", "cycling"}, true};
    json j_alice = alice; // 自动调用 to_json(j_alice, alice)
    std::cout << "Alice as JSON:\n" << j_alice.dump(4) << std::endl;

    // 2. 将 JSON 反序列化为 C++ 对象
    json j_bob = R"(
        {
            "name": "Bob",
            "age": 30,
            "hobbies": ["gaming", "hiking"],
            "is_student": false
        }
    )"_json; // 使用 _json 字面量操作符解析字符串

    Person bob = j_bob.get<Person>(); // 自动调用 from_json(j_bob, bob)

    std::cout << "\nBob (from JSON):\n";
    std::cout << "Name: " << bob.name << std::endl;
    std::cout << "Age: " << bob.age << std::endl;
    std::cout << "Hobbies: ";
    for (const auto& hobby : bob.hobbies) {
        std::cout << hobby << " ";
    }
    std::cout << "\nIs Student: " << (bob.is_student ? "Yes" : "No") << std::endl;

    // 错误处理:如果 JSON 缺少某个字段,from_json 会抛出异常
    json invalid_json = R"({"name": "Eve", "age": 22})"_json;
    try {
        Person eve = invalid_json.get<Person>();
    } catch (const json::exception& e) {
        std::cerr << "\nError deserializing invalid_json: " << e.what() << std::endl;
    }

    return 0;
}

2.4.2 JSON Pointer

JSON Pointer (RFC 6901) 提供了一种标准化的方式来在JSON文档中定位特定的值。nlohmann/json 完全支持JSON Pointer。

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json doc = R"(
        {
            "foo": ["bar", "baz"],
            "": 0,
            "a/b": 1,
            "c%d": 2,
            "e^f": 3,
            "g|h": 4,
            "i\\j": 5,
            "k\"l": 6,
            " ": 7,
            "m~n": 8,
            "object": {
                "nested_key": "nested_value"
            },
            "array": [
                {"item1": "value1"},
                {"item2": "value2"}
            ]
        }
    )"_json;

    // 使用 JSON Pointer 访问元素
    std::cout << "doc[\"/foo/0\"]: " << doc.at("/foo/0") << std::endl;         // "bar"
    std::cout << "doc[\"/a~1b\"]: " << doc.at("/a~1b") << std::endl;           // 1  (斜杠编码为 ~1)
    std::cout << "doc[\"/m~0n\"]: " << doc.at("/m~0n") << std::endl;           // 8  (波浪号编码为 ~0)
    std::cout << "doc[\"/object/nested_key\"]: " << doc.at("/object/nested_key") << std::endl; // "nested_value"
    std::cout << "doc[\"/array/0/item1\"]: " << doc.at("/array/0/item1") << std::endl; // "value1"

    // JSON Pointer 赋值
    doc["/foo/1"] = "qux";
    std::cout << "\nModified doc (foo/1):\n" << doc.dump(4) << std::endl;

    // JSON Pointer 添加新值
    doc["/new_key"] = "new_value";
    std::cout << "\nModified doc (new_key):\n" << doc.dump(4) << std::endl;

    // 检查是否存在
    if (doc.contains("/object/nested_key")) {
        std::cout << "\n'/object/nested_key' exists." << std::endl;
    }

    // 错误处理:访问不存在的 JSON Pointer
    try {
        std::cout << doc.at("/non_existent_path") << std::endl;
    } catch (const json::exception& e) {
        std::cerr << "Error accessing non-existent path: " << e.what() << std::endl;
    }

    return 0;
}

2.4.3 JSON Patch

JSON Patch ([[RFC 6902]]) 定义了一种标准的数据格式,用于描述对JSON文档的更改。nlohmann/json 提供了对JSON Patch 的支持,包括生成和应用补丁。

#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main() {
    json document = R"(
        {
            "baz": "qux",
            "foo": ["bar", "baz"],
            "glossary": {
                "title": "example glossary"
            }
        }
    )"_json;

    json other_document = R"(
        {
            "baz": "boo",
            "foo": ["bar", "boo"],
            "test": "hello",
            "glossary": {
                "title": "updated glossary"
            }
        }
    )"_json;

    std::cout << "Original Document:\n" << document.dump(4) << std::endl;
    std::cout << "\nOther Document:\n" << other_document.dump(4) << std::endl;

    // 1. 生成 JSON Patch
    // 计算从 document 到 other_document 的差异
    json patch = json::diff(document, other_document);
    std::cout << "\nGenerated JSON Patch:\n" << patch.dump(4) << std::endl;

    // 2. 应用 JSON Patch
    json patched_document = document.patch(patch);
    std::cout << "\nDocument after applying patch:\n" << patched_document.dump(4) << std::endl;

    // 验证补丁是否正确应用
    if (patched_document == other_document) {
        std::cout << "\nPatched document matches other_document." << std::endl;
    } else {
        std::cout << "\nPatched document does NOT match other_document." << std::endl;
    }

    // 手动创建 JSON Patch
    json manual_patch = json::array({
        {{"op", "replace"}, {"path", "/baz"}, {"value", "new_qux"}},
        {{"op", "add"}, {"path", "/new_key"}, {"value", 123}},
        {{"op", "remove"}, {"path", "/foo/0"}}
    });

    json doc_to_patch = document; // 复制一份进行操作
    try {
        doc_to_patch = doc_to_patch.patch(manual_patch);
        std::cout << "\nDocument after applying manual patch:\n" << doc_to_patch.dump(4) << std::endl;
    } catch (const json::exception& e) {
        std::cerr << "Error applying manual patch: " << e.what() << std::endl;
    }

    return 0;
}

结论

nlohmann/json 库凭借其仅头文件、直观的API设计、强大的功能集以及对C++现代特性的充分利用,已成为C++处理JSON数据的首选解决方案。它不仅简化了JSON的解析和序列化过程,还通过支持JSON Pointer 和 JSON Patch 等高级特性,极大地提升了C++在复杂数据操作方面的能力。无论是小型配置解析还是大型系统间的数据交换,nlohmann/json 都能提供一个高效、可靠且易于维护的工具。随着C++标准的不断演进,nlohmann/json 也将继续保持其领先地位,为C++开发者提供更加便捷和强大的JSON处理体验。


参考文献

  • [1] nlohmann/json GitHub Repository: https://github.com/nlohmann/json
  • [2] JSON (JavaScript Object Notation) - ECMA-404 The JSON Data Interchange Format: https://www.ecma-international.org/publications-and-standards/standards/ecma-404/
  • [3] RFC 6901 - JSON Pointer: https://tools.ietf.org/html/rfc6901
  • [4] RFC 6902 - JSON Patch: https://tools.ietf.org/html/rfc6902