嵌入式高性能 JSON 处理:nlohmann::json 与 rapidjson 选型及通用用法

一、库概述

1. 整体定位

两者均为C++生态下主流的JSON数据处理库,专注于JSON格式的数据序列化(JSON→字符串)与反序列化(字符串→JSON),支撑跨平台、跨系统的数据交互场景,核心设计理念存在显著差异:

  • nlohmann::json:以「开发易用性」为核心导向,API设计贴近C++ STL容器,语法简洁直观,大幅降低JSON操作的学习与使用成本。
  • rapidjson:以「极致性能与内存可控性」为核心导向,轻量级零依赖,支持精细化内存管理,在高吞吐、低延迟的场景下具备显著优势。
  • 两者均为纯头文件库,无需单独编译生成动态库/静态库,直接引入头文件即可集成使用,具备良好的跨平台兼容性。

2. 共性特征

  1. 支持JSON核心数据类型(字符串、整数、浮点数、布尔值、对象、数组、空值)的完整操作;
  2. 支持嵌套JSON结构(对象嵌套对象、对象嵌套数组等);
  3. 支持JSON与C++基础数据类型的相互转换;
  4. 无第三方运行时依赖,适配桌面端、嵌入式端等多种运行环境。

二、环境准备(基于CMake构建)

1. 库获取与集成

(1)nlohmann::json 集成

两种通用集成方式,适配不同开发场景:

  • 方式1:手动集成

    1. 从官方仓库下载核心头文件 json.hpp;
    2. 在项目目录下创建 include/nlohmann/ 目录,将 json.hpp 放入该目录;
    3. 代码中通过 #include <nlohmann/json.hpp> 直接引入。
  • 方式2:包管理器集成
    以Ubuntu系统为例:

    sudo apt-get install nlohmann-json3-dev
    
(2)rapidjson 集成

两种通用集成方式,与nlohmann::json保持一致适配逻辑:

  • 方式1:手动集成

    1. 从官方仓库下载源码包;
    2. 提取源码中的 include/rapidjson/ 目录,拷贝到项目的 include/ 目录下;
    3. 代码中通过 #include <rapidjson/document.h> 等头文件引入对应模块。
  • 方式2:包管理器集成
    以Ubuntu系统为例:

    sudo apt-get install rapidjson-dev
    

2. CMakeLists.txt 通用配置

以下配置为通用模板,适配手动集成与包管理器集成两种方式,无业务相关依赖,可直接复用:

cmake_minimum_required(VERSION 3.10)
project(JsonGeneralDemo)

# 配置C++标准(nlohmann::json推荐C++17,rapidjson支持C++03及以上,统一指定C++17兼容两者)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 嵌入式场景:静态链接(避免依赖动态库)
set(CMAKE_LINK_STATIC_LIBS ON)
set(CMAKE_EXE_LINKER_FLAGS "-static")

# 1. 配置头文件搜索目录(手动集成时,指定项目内头文件路径)
include_directories(
    ${PROJECT_SOURCE_DIR}/include  # 对应手动拷贝的nlohmann/rapidjson头文件目录
    ${PROJECT_SOURCE_DIR}/src
)

# 2. (可选)包管理器集成时,自动查找库(本地开发环境适用)
find_package(nlohmann_json 3.0.0 REQUIRED)
find_package(RapidJSON REQUIRED)
include_directories(${RAPIDJSON_INCLUDE_DIRS})

# 3. 构建可执行文件(替换为通用源码文件,无业务关联)
add_executable(JsonGeneralDemo
    src/main.cpp
)

# 4. (可选)包管理器集成时,绑定库依赖(仅头文件依赖,无二进制链接)
target_link_libraries(JsonGeneralDemo PRIVATE nlohmann_json::nlohmann_json)

# 嵌入式专属编译优化(针对ARM等架构)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") # 移除未使用的函数/数据段,减小文件体积

3. 交叉编译通用适配

针对嵌入式Linux等交叉编译场景,无需额外编译库文件,通用适配步骤如下:

  1. 将 nlohmann/ 与 rapidjson/ 头文件目录拷贝到交叉编译工具链的 sysroot/usr/include/ 目录下;
    示例(arm-linux-gnueabihf工具链):
    # 拷贝头文件到工具链目录
    cp -r nlohmann/ /opt/arm-linux-gnueabihf/sysroot/usr/include/
    cp -r rapidjson/ /opt/arm-linux-gnueabihf/sysroot/usr/include/
    
  2. 在CMake工具链配置文件(如 toolchain_arm_linux.cmake)中,确保 C_INCLUDE_PATH 与 CXX_INCLUDE_PATH 包含头文件所在目录;
    工具链文件示例片段:
    set(CMAKE_SYSTEM_NAME Linux)
    set(CMAKE_SYSTEM_PROCESSOR arm)
    set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
    set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
    # 指定头文件目录
    set(C_INCLUDE_PATH /opt/arm-linux-gnueabihf/sysroot/usr/include)
    set(CXX_INCLUDE_PATH /opt/arm-linux-gnueabihf/sysroot/usr/include)
    
  3. 保持编译选项与本地一致,无需额外添加链接参数(纯头文件库无二进制依赖)。

三、核心通用用法

1. 基本操作:JSON对象的创建与取值

(1)nlohmann::json 通用用法
#include <nlohmann/json.hpp>
#include <string>
#include <iostream>

// 命名空间别名(通用简化写法)
namespace json = nlohmann;

void nlohmann_json_basic_operation() {
    // 1. 创建空JSON对象
    json::json json_obj;

    // 2. 添加各类类型成员(直接赋值,类似STL map)
    json_obj["string_key"] = "hello world";
    json_obj["int_key"] = 100;
    json_obj["double_key"] = 3.14159;
    json_obj["bool_key"] = true;
    json_obj["null_key"] = nullptr;

    // 3. 嵌套JSON对象创建
    json_obj["nested_obj"]["key1"] = "nested value";
    json_obj["nested_obj"]["key2"] = 200;

    // 4. 取值操作(直接索引,自动类型转换)
    std::string str_val = json_obj["string_key"];
    int int_val = json_obj["int_key"];
    double double_val = json_obj["double_key"];
    bool bool_val = json_obj["bool_key"];

    // 5. 类型判断(可选,提高代码健壮性)
    if (json_obj["string_key"].is_string()) {
        std::cout << "string_key is string type" << std::endl;
    }
    if (json_obj["nested_obj"].is_object()) {
        std::cout << "nested_obj is object type" << std::endl;
    }

    // 6. 成员存在性判断
    if (json_obj.contains("int_key")) {
        std::cout << "int_key exists, value: " << json_obj["int_key"] << std::endl;
    }
}
(2)rapidjson 通用用法
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <string>
#include <iostream>

// 命名空间别名(通用简化写法)
namespace rapid = rapidjson;

void rapidjson_basic_operation() {
    // 1. 创建空JSON对象,获取内存分配器
    rapid::Document doc(rapid::kObjectType);
    rapid::Document::AllocatorType& allocator = doc.GetAllocator();

    // 2. 添加各类类型成员(需通过rapid::Value构建值对象)
    // 字符串类型:需指定分配器,使用Move语义减少拷贝
    doc.AddMember("string_key", rapid::Value("hello world", allocator).Move(), allocator);
    // 数值类型:直接赋值
    doc.AddMember("int_key", 100, allocator);
    doc.AddMember("double_key", 3.14159, allocator);
    // 布尔类型
    doc.AddMember("bool_key", true, allocator);
    // 空值类型
    doc.AddMember("null_key", rapid::Value(rapid::kNullType).Move(), allocator);

    // 嵌入式场景:使用常量字符串(无需Allocator分配内存,减少堆操作)
    rapid::Value const_str_val(rapid::kStringType);
    const_str_val.SetString("constant_str", rapid::StringRef("constant_str").Length());
    doc.AddMember("const_key", const_str_val.Move(), allocator);

    // 3. 嵌套JSON对象创建
    rapid::Value nested_obj(rapid::kObjectType);
    nested_obj.AddMember("key1", rapid::Value("nested value", allocator).Move(), allocator);
    nested_obj.AddMember("key2", 200, allocator);
    doc.AddMember("nested_obj", nested_obj.Move(), allocator);

    // 4. 取值操作(先判断成员存在性与类型,避免程序崩溃)
    if (doc.HasMember("string_key") && doc["string_key"].IsString()) {
        std::string str_val = doc["string_key"].GetString();
        std::cout << "string_key value: " << str_val << std::endl;
    }
    if (doc.HasMember("int_key") && doc["int_key"].IsInt()) {
        int int_val = doc["int_key"].GetInt();
        std::cout << "int_key value: " << int_val << std::endl;
    }
    if (doc.HasMember("double_key") && doc["double_key"].IsDouble()) {
        double double_val = doc["double_key"].GetDouble();
        std::cout << "double_key value: " << double_val << std::endl;
    }
    if (doc.HasMember("nested_obj") && doc["nested_obj"].IsObject()) {
        const rapid::Value& nested = doc["nested_obj"];
        if (nested.HasMember("key1") && nested["key1"].IsString()) {
            std::string nested_val = nested["key1"].GetString();
            std::cout << "nested_obj.key1 value: " << nested_val << std::endl;
        }
    }
}

2. 序列化与反序列化:JSON ↔ 字符串

(1)nlohmann::json 通用用法
#include <nlohmann/json.hpp>
#include <string>
#include <iostream>

namespace json = nlohmann;

void nlohmann_json_serialize_deserialize() {
    // 1. JSON对象序列化为字符串
    json::json json_obj;
    json_obj["key1"] = "value1";
    json_obj["key2"] = 123;

    // 紧凑格式(无空格、无换行,适合嵌入式存储/传输)
    std::string compact_str = json_obj.dump();
    // 格式化格式(带缩进,适合调试/日志输出)
    std::string pretty_str = json_obj.dump(4); // 4个空格缩进

    std::cout << "Compact JSON string: " << compact_str << std::endl;
    std::cout << "Pretty JSON string: " << pretty_str << std::endl;

    // 2. 字符串反序列化为JSON对象
    std::string raw_json = R"({"name":"test","age":20})";
    try {
        // 解析字符串
        json::json parsed_json = json::json::parse(raw_json);
        // 取值使用
        std::string name = parsed_json["name"];
        int age = parsed_json["age"];
        std::cout << "Parsed name: " << name << ", age: " << age << std::endl;
    } catch (const json::json::parse_error& e) {
        // 捕获解析异常
        std::cerr << "JSON parse error: " << e.what() << std::endl;
    }
}
(2)rapidjson 通用用法
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/prettywriter.h>
#include <string>
#include <iostream>

namespace rapid = rapidjson;

void rapidjson_serialize_deserialize() {
    // 1. JSON对象序列化为字符串
    rapid::Document doc(rapid::kObjectType);
    rapid::Document::AllocatorType& allocator = doc.GetAllocator();
    doc.AddMember("key1", rapid::Value("value1", allocator).Move(), allocator);
    doc.AddMember("key2", 123, allocator);

    // 紧凑格式(无空格、无换行,适合嵌入式存储/传输)
    rapid::StringBuffer compact_buffer;
    rapid::Writer<rapid::StringBuffer> compact_writer(compact_buffer);
    doc.Accept(compact_writer);
    std::string compact_str = compact_buffer.GetString();

    // 格式化格式(带缩进)
    rapid::StringBuffer pretty_buffer;
    rapid::PrettyWriter<rapid::StringBuffer> pretty_writer(pretty_buffer);
    doc.Accept(pretty_writer);
    std::string pretty_str = pretty_buffer.GetString();

    std::cout << "Compact JSON string: " << compact_str << std::endl;
    std::cout << "Pretty JSON string: " << pretty_str << std::endl;

    // 2. 字符串反序列化为JSON对象
    std::string raw_json = R"({"name":"test","age":20})";
    rapid::Document parsed_doc;
    // 解析字符串,判断是否解析失败
    if (parsed_doc.Parse(raw_json.c_str()).HasParseError()) {
        std::cerr << "JSON parse error, code: " << parsed_doc.GetParseError() << std::endl;
        return;
    }

    // 取值使用
    if (parsed_doc.HasMember("name") && parsed_doc["name"].IsString()) {
        std::string name = parsed_doc["name"].GetString();
        std::cout << "Parsed name: " << name << std::endl;
    }
    if (parsed_doc.HasMember("age") && parsed_doc["age"].IsInt()) {
        int age = parsed_doc["age"].GetInt();
        std::cout << "Parsed age: " << age << std::endl;
    }
}

3. 通用操作:JSON数组

(1)nlohmann::json 通用用法
#include <nlohmann/json.hpp>
#include <string>
#include <iostream>
#include <vector>

namespace json = nlohmann;

void nlohmann_json_array_operation() {
    // 1. 创建JSON数组
    json::json json_array;

    // 2. 添加元素(支持多种类型)
    json_array.push_back("element1");
    json_array.push_back(456);
    json_array.push_back(2.718);
    json_array.push_back(false);
    // 数组中嵌套对象
    json::json nested_obj;
    nested_obj["nested_key"] = "nested_val";
    json_array.push_back(nested_obj);

    // 3. 遍历数组(支持范围for循环,类似STL容器)
    for (size_t i = 0; i < json_array.size(); ++i) {
        std::cout << "Array index " << i << ": " << json_array[i] << std::endl;
    }
    // 范围for遍历
    for (const auto& elem : json_array) {
        std::cout << "Array element: " << elem << std::endl;
    }

    // 4. 取值操作
    std::string first_elem = json_array[0];
    int second_elem = json_array[1];
    std::cout << "First element: " << first_elem << std::endl;
    std::cout << "Second element: " << second_elem << std::endl;

    // 5. 数组与C++ vector互转
    std::vector<int> int_vec = {1,2,3,4,5};
    // vector → JSON数组
    json::json vec_to_json = int_vec;
    // JSON数组 → vector
    std::vector<int> json_to_vec = vec_to_json.get<std::vector<int>>();
}
(2)rapidjson 通用用法
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <string>
#include <iostream>
#include <vector>

namespace rapid = rapidjson;

void rapidjson_array_operation() {
    // 1. 创建JSON数组
    rapid::Document doc(rapid::kArrayType);
    rapid::Document::AllocatorType& allocator = doc.GetAllocator();

    // 2. 添加元素(支持多种类型,使用PushBack + Move语义)
    doc.PushBack(rapid::Value("element1", allocator).Move(), allocator);
    doc.PushBack(456, allocator);
    doc.PushBack(2.718, allocator);
    doc.PushBack(false, allocator);
    // 数组中嵌套对象
    rapid::Value nested_obj(rapid::kObjectType);
    nested_obj.AddMember("nested_key", rapid::Value("nested_val", allocator).Move(), allocator);
    doc.PushBack(nested_obj.Move(), allocator);

    // 3. 遍历数组(使用SizeType索引,无范围for原生支持)
    for (rapid::SizeType i = 0; i < doc.Size(); ++i) {
        const rapid::Value& elem = doc[i];
        std::cout << "Array index " << i << ": ";
        if (elem.IsString()) {
            std::cout << elem.GetString() << std::endl;
        } else if (elem.IsInt()) {
            std::cout << elem.GetInt() << std::endl;
        } else if (elem.IsDouble()) {
            std::cout << elem.GetDouble() << std::endl;
        } else if (elem.IsBool()) {
            std::cout << (elem.GetBool() ? "true" : "false") << std::endl;
        } else if (elem.IsObject()) {
            std::cout << "nested object" << std::endl;
        }
    }

    // 4. 取值操作(先判断类型)
    if (doc.Size() > 0 && doc[0].IsString()) {
        std::string first_elem = doc[0].GetString();
        std::cout << "First element: " << first_elem << std::endl;
    }
    if (doc.Size() > 1 && doc[1].IsInt()) {
        int second_elem = doc[1].GetInt();
        std::cout << "Second element: " << second_elem << std::endl;
    }

    // 5. 数组与C++ vector互转(手动遍历实现)
    std::vector<int> int_vec = {1,2,3,4,5};
    // vector → rapidjson数组
    rapid::Value vec_to_array(rapid::kArrayType);
    for (int val : int_vec) {
        vec_to_array.PushBack(val, allocator);
    }
    // rapidjson数组 → vector
    std::vector<int> array_to_vec;
    if (vec_to_array.IsArray()) {
        for (rapid::SizeType i = 0; i < vec_to_array.Size(); ++i) {
            if (vec_to_array[i].IsInt()) {
                array_to_vec.push_back(vec_to_array[i].GetInt());
            }
        }
    }
}

4. 通用结构体与JSON互转

(1)nlohmann::json 通用用法(支持自动/手动互转)
#include <nlohmann/json.hpp>
#include <string>

namespace json = nlohmann;

// 通用测试结构体
struct CommonStruct {
    std::string str_member;
    int int_member;
    double double_member;
    bool bool_member;
};

// 方式1:手动互转(通用灵活,精准控制字段)
void struct_to_nlohmann_json(json::json& j, const CommonStruct& s) {
    j["str_member"] = s.str_member;
    j["int_member"] = s.int_member;
    j["double_member"] = s.double_member;
    j["bool_member"] = s.bool_member;
}

void nlohmann_json_to_struct(const json::json& j, CommonStruct& s) {
    if (j.contains("str_member")) {
        s.str_member = j["str_member"];
    }
    if (j.contains("int_member")) {
        s.int_member = j["int_member"];
    }
    if (j.contains("double_member")) {
        s.double_member = j["double_member"];
    }
    if (j.contains("bool_member")) {
        s.bool_member = j["bool_member"];
    }
}

// 方式2:自动互转(简洁高效,需启用宏)
// 宏参数:结构体类型 + 成员变量列表(需与JSON字段名一致)
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(CommonStruct, str_member, int_member, double_member, bool_member)

void nlohmann_json_struct_convert() {
    CommonStruct s = {"test", 100, 3.14, true};

    // 手动互转
    json::json j1;
    struct_to_nlohmann_json(j1, s);
    CommonStruct s1;
    nlohmann_json_to_struct(j1, s1);

    // 自动互转
    json::json j2 = s; // 结构体 → JSON
    CommonStruct s2 = j2.get<CommonStruct>(); // JSON → 结构体
}
(2)rapidjson 通用用法(仅支持手动互转)
#include <rapidjson/document.h>
#include <string>

namespace rapid = rapidjson;

// 通用测试结构体
struct CommonStruct {
    std::string str_member;
    int int_member;
    double double_member;
    bool bool_member;
};

// 结构体 → rapidjson Value
void struct_to_rapidjson_value(const CommonStruct& s, rapid::Value& val, rapid::Document::AllocatorType& allocator) {
    val.SetObject();
    val.AddMember("str_member", rapid::Value(s.str_member.c_str(), allocator).Move(), allocator);
    val.AddMember("int_member", s.int_member, allocator);
    val.AddMember("double_member", s.double_member, allocator);
    val.AddMember("bool_member", s.bool_member, allocator);
}

// rapidjson Value → 结构体
void rapidjson_value_to_struct(const rapid::Value& val, CommonStruct& s) {
    if (val.HasMember("str_member") && val["str_member"].IsString()) {
        s.str_member = val["str_member"].GetString();
    }
    if (val.HasMember("int_member") && val["int_member"].IsInt()) {
        s.int_member = val["int_member"].GetInt();
    }
    if (val.HasMember("double_member") && val["double_member"].IsDouble()) {
        s.double_member = val["double_member"].GetDouble();
    }
    if (val.HasMember("bool_member") && val["bool_member"].IsBool()) {
        s.bool_member = val["bool_member"].GetBool();
    }
}

void rapidjson_struct_convert() {
    CommonStruct s = {"test", 100, 3.14, true};
    rapid::Document doc(rapid::kObjectType);
    rapid::Document::AllocatorType& allocator = doc.GetAllocator();

    // 结构体 → rapidjson Value
    rapid::Value val(rapid::kObjectType);
    struct_to_rapidjson_value(s, val, allocator);
    doc.AddMember("struct_data", val.Move(), allocator);

    // rapidjson Value → 结构体
    CommonStruct s_parse;
    if (doc.HasMember("struct_data") && doc["struct_data"].IsObject()) {
        rapidjson_value_to_struct(doc["struct_data"], s_parse);
    }
}

四、核心异同点对比

对比维度nlohmann::jsonrapidjson
设计核心易用性优先,贴近STL语法性能优先,精细化内存管理
API风格简洁直观,支持直接赋值/取值手动管控,依赖Value/Allocator对象
性能表现优秀,满足绝大多数通用场景极致性能,内存拷贝少,吞吐率更高
内存占用略高(自动内存管理,存在冗余开销)极低(手动内存管理,无冗余开销)
结构体互转支持自动/手动互转,灵活可选仅支持手动互转,精准可控
异常处理解析失败抛出C++异常,需try-catch捕获解析失败返回错误码,无异常抛出
格式化输出内置dump(n)方法,直接生成格式化字符串需使用PrettyWriter类,额外配置
C++标准兼容支持C++11及以上,推荐C++17支持C++03及以上,兼容性更强
学习成本低,无需记忆复杂API,快速上手较高,需理解内存分配器、Move语义等
功能冗余度高,内置多种便捷工具方法低,仅保留核心功能,轻量级
嵌入式适配性良好,可通过宏裁剪功能极佳,支持内存池、无堆内存依赖

共性总结

  1. 均为纯头文件库,无需编译二进制库,跨平台兼容性强;
  2. 均支持JSON核心数据类型与嵌套结构的完整操作;
  3. 均支持JSON与字符串的序列化/反序列化;
  4. 均支持手动实现结构体与JSON的相互转换;
  5. 无第三方运行时依赖,适配桌面端、嵌入式端等场景。

五、通用注意事项

1. 异常处理

  • nlohmann::json 解析无效JSON、类型转换失败时会抛出异常,生产环境中需使用try-catch捕获对应异常类型:
    try {
        auto j = json::json::parse("invalid json");
    } catch (const json::json::exception& e) {
        // 捕获所有nlohmann::json相关异常
        std::cerr << "JSON error: " << e.what() << std::endl;
    }
    
  • rapidjson 无异常抛出,通过HasParseError()判断解析状态,通过HasMember()+类型判断避免取值崩溃,更适合高可靠性场景:
    rapid::Document doc;
    if (doc.Parse("invalid json").HasParseError()) {
        std::cerr << "Parse error at offset " << doc.GetErrorOffset() << std::endl;
    }
    

2. 内存管理

  • nlohmann::json 自动管理内存,无需手动干预,可使用swap()方法减少大数据量场景下的内存拷贝;
  • rapidjson 推荐使用Move()语义(Value::Move())传递对象,避免不必要的内存拷贝,提升性能;
  • 两者在嵌入式内存受限场景下均适用,rapidjson的内存占用优势更为显著。

3. 字符串处理

  • nlohmann::json 支持C++ std::string直接赋值与取值,无需额外内存管理;
  • rapidjson 字符串值需依赖Allocator分配内存,推荐使用rapid::Value(str, allocator).Move()的方式构建,避免内存泄漏;
  • 嵌入式场景下,优先使用rapid::StringRef处理常量字符串,减少堆内存分配操作。

4. 类型安全

  • 两者均需保证JSON字段类型与取值类型一致,nlohmann::json 类型不匹配时会抛出异常,rapidjson 类型不匹配时会导致未定义行为;
  • 生产环境中,无论使用哪个库,均建议先进行类型判断,再执行取值操作,提高代码健壮性。

5. 编译优化

  • 两者均可通过CMake配置编译优化选项(如-O2),进一步提升运行性能;
  • rapidjson 可通过定义宏(如RAPIDJSON_HAS_STDSTRING)开启std::string兼容支持,简化字符串操作。

六、嵌入式场景专属选型建议

  1. 优先选 rapidjson 的场景

    • 实时性要求高:如传感器数据实时序列化(雷达、摄像头)、通信协议(TCP/UDP/WebSocket)高频数据传输;
    • 内存/存储受限:如小型嵌入式设备(MCU、低端ARM板)、无操作系统(RTOS)环境;
    • 高可靠性要求:如工业控制、车载设备,需避免异常抛出,依赖错误码处理故障。
  2. 优先选 nlohmann::json 的场景

    • 开发效率优先:如嵌入式设备的配置解析(Flash/配置文件读取)、日志记录,无需极致性能;
    • 复杂数据结构:如嵌套多层的配置对象、需要与STL容器快速互转,减少手动代码编写;
    • 桌面端与嵌入式共用代码:一套代码适配桌面调试与嵌入式部署,降低移植成本。
  3. 混合使用场景

    • 嵌入式设备中,「配置解析」使用 nlohmann::json(开发高效),「实时数据传输」使用 rapidjson(性能优先),兼顾开发效率与运行性能。

更多推荐