【学习笔记】nlohmannjson&&cjson

【学习笔记】nlohmann::json&&cjson

json 复制代码
[
    {

       "nodeId":1,
       "refreshRate": 6000,

        "brightness":
        {
                "B": 50, 
                "G": 50, 
                "R": 50,
                "all": 50
         }
    }
]

将上面的数据分别使用nlohmann::json或者cjson实现出来。

一、cjson

c++ 复制代码
#include "cJSON.h"
#include <iostream>
#include <string>

int main() {
    // 创建JSON数组  //root: [ ]
    cJSON* root = cJSON_CreateArray();
    
    // 创建第一个节点对象 node: { }
    cJSON* node = cJSON_CreateObject();
    cJSON_AddNumberToObject(node, "nodeId", 1);
    cJSON_AddNumberToObject(node, "refreshRate", 6000);
    
    // 创建亮度对象brightness: { }
    cJSON* brightness = cJSON_CreateObject();
    cJSON_AddNumberToObject(brightness, "B", 50);
    cJSON_AddNumberToObject(brightness, "G", 50);
    cJSON_AddNumberToObject(brightness, "R", 50);
    cJSON_AddNumberToObject(brightness, "all", 50);
    
    // 将亮度对象添加到节点
    cJSON_AddItemToObject(node, "brightness", brightness);
    
    // 将节点添加到数组
    cJSON_AddItemToArray(root, node);
    
    // 转换为格式化的JSON字符串
    char* jsonString = cJSON_Print(root);
    if (jsonString) {
        std::cout << jsonString << std::endl;
        free(jsonString);  // 释放由cJSON_Print分配的内存
    }
    
    // 释放JSON结构占用的内存
    cJSON_Delete(root);
    
    return 0;
}

​ ● 单文件实现:仅包含 cJSON.c 和 cJSON.h,无需额外依赖,适合嵌入式系统或资源受限环境。

​ ● C 语言兼容性:纯 C 实现,可无缝集成到 C 或 C++ 项目中,不依赖 C++ 标准库。

​ ● 精简的内存模型:采用链表结构存储 JSON 节点,内存占用小,解析速度快(尤其适合小到中型 JSON)。

​ ● 无 STL 依赖:避免了 C++ 标准库的开销,在低性能设备上表现更优。

​ ● 函数式接口:通过 cJSON_Create*、cJSON_Add* 等函数操作 JSON,学习成本低。

​ ● 手动内存管理:允许精细控制内存分配,适合对内存使用敏感的场景。需要手动释放。

二、nlohmann/json

1、nlohmann/json(嵌套赋值)

c++ 复制代码
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main() {
    // 创建空的JSON对象
    json layer_json;

    // 直接使用嵌套赋值(自动创建中间对象)
    layer_json["brightness"]["B"] = 50;
    layer_json["brightness"]["G"] = 50;
    layer_json["brightness"]["R"] = 50;
    layer_json["brightness"]["all"] = 50;

    // 添加其他字段
    layer_json["nodeId"] = 1;
    layer_json["refreshRate"] = 6000;

    // 输出JSON(格式化,缩进4空格)
    std::cout << layer_json.dump(4) << std::endl;

    return 0;
}

2、nlohmann/json(初始化列表)

c++ 复制代码
#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main() {
    // 创建JSON数组
    json jsonArray = json::array();

    // 创建第一个节点对象
    json node = {
        {"nodeId", 1},
        {"refreshRate", 6000},
        {"brightness", {
            {"B", 50},
            {"G", 50},
            {"R", 50},
            {"all", 50}
        }}
    };

    // 将节点添加到数组
    jsonArray.push_back(node);

    // 输出JSON(格式化,缩进4空格)
    std::cout << jsonArray.dump(4) << std::endl;

    return 0;
}

3、初始化列表/嵌套赋值差异

​ ● 嵌套赋值:像 "积木",适合逐步组装动态结构。

​ ● 初始化列表:像 "蓝图",适合一次性构建静态结构。

维度 初始化列表方式 嵌套赋值方式
实现机制 一次性构造完整 JSON 结构 动态创建并修改 JSON 结构
适用场景 静态已知的 JSON 结构(编译时确定) 动态生成或修改的 JSON(运行时确定)
代码风格 声明式(类似 JSON 字面量) 命令式(类似 JavaScript 对象操作)
性能 通常略高效(一次性分配内存) 可能多次内存分配(动态扩展)
错误处理 编译时类型检查(如 nodeId 必须为数值) 运行时可能抛出异常
缺点 灵活性低:必须预先知道完整结构,无法动态调整。嵌套层级过深时可读性下降:多层嵌套会导致代码冗长。 潜在性能开销:每次访问不存在的键时会自动创建对象,可能触发多次内存分配。运行时错误风险:若键名拼写错误,会创建新字段而非报错(如 layer_json"brightnes""B")。
性能对比 运行时分配内存:分配内存 → 一次性构造所有节点 → 完成 运行时分配内存:访问 layer_json → 检查 "brightness" 是否存在 → 不存在则创建对象访问 "brightness" → 检查 "B" 是否存在 → 不存在则创建并赋值重复上述步骤...

4、nlohmann优势

​ ● 自动资源管理:避免手动内存管理,减少内存泄漏风险。

​ ● 小对象优化:对于小 JSON 对象(如只含几个字段),直接在栈上分配内存,减少堆分配开销。

​ ● 编译时检查:编译的时候检查类型,类型安全。

​ ● 基准测试:在处理中等大小 JSON(1MB)时,nlohmann/json 的解析速度通常比其他 C++ 库快 20%~50%。

​ ● 支持STL 风格接口:支持容器式操作和迭代器支持。

c++ 复制代码
for (auto& element : j["hobbies"]) {  // 支持范围for循环
    std::cout << element << std::endl;
}

j["scores"].push_back(95);  // 类似vector的操作
c++ 复制代码
for (auto it = j.begin(); it != j.end(); ++it) {
    std::cout << it.key() << ": " << it.value() << std::endl;
}

​ ● 自动序列化 / 反序列化:支持序列化和反序列化。

c++ 复制代码
struct Person {
    std::string name;
    int age;
};

// 只需定义to_json/from_json函数
void to_json(json& j, const Person& p) {
    j = {{"name", p.name}, {"age", p.age}};
}

void from_json(const json& j, Person& p) {
    p.name = j.at("name").get<std::string>();
    p.age = j.at("age").get<int>();
}

// 使用示例
Person p = {"Alice", 30};
json j = p;  // 自动序列化
Person p2 = j.get<Person>();  // 自动反序列化
相关推荐
数据狐(Datafox)7 分钟前
淘宝商品详情API实战:多语言代购商城自动同步数据完整方案
开发语言·前端·数据库·爬虫·json
2601_9622186121 分钟前
C++ string 类原理、踩坑与对象语义详解
开发语言·c++
李游Leo22 分钟前
HarmonyOS 7 + ArkTS + NAPI 学习笔记:Native 模块桥接、CMake 构建与跨语言调用实践【鸿蒙心迹】
笔记·学习·harmonyos
爱写代码的小朋友37 分钟前
Windows 下 MSYS2 + MinGW64 安装与使用 OpenCV 全指南(含踩坑记录)
c++·人工智能·windows·opencv
重生之小比特1 小时前
【C++进阶】封装红⿊树实现mymap和myset
开发语言·c++
边境悍匪1 小时前
蜗牛学苑 Java 智能体学习 Day49|贯穿项目 5 订单下单业务 思维导图复盘
java·开发语言·spring boot·学习·阿里云
YYYing.1 小时前
【设计模式系列 (四) 】建造者模式
c++·后端·设计模式·建造者模式·c/c++
羑悻的小杀马特1 小时前
Docker高阶实战:从Redis集群到C++微服务,全面解析镜像优化与生产环境部署+镜像制作常见问题详解
c++·redis·docker·镜像制作·dockefile
别动我齐刘海1 小时前
ROS2 Jazzy + C++ 时间系统——Time / Clock / Duration
linux·c++·人工智能·学习·机器学习·机器人·自动驾驶
小范的技术工坊1 小时前
大模型学习操作文档(13个核心概念串讲)
人工智能·学习·算法·大模型