【学习笔记】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>(); // 自动反序列化