C++ JSON库的使用示例

1. JSON 创建

(1)创建 JSON 对象

json j;
j["name"] = "三三";
j["age"] = 20;
j["skills"] = { "C++", "Python", "Go" };

等效于:

{
    "name": "三三",
    "age": 20,
    "skills": ["C++", "Python", "Go"]
}

(2)使用 initializer_list 直接构造

json j = {
    {"name", "三三"},
    {"age", 20},
    {"skills", {"C++", "Python", "Go"}}
};

(3)创建 JSON 数组

json arr = json::array({1, 2, 3, 4, 5});

等效于:

[1, 2, 3, 4, 5]

2. 访问与修改 JSON

(1)访问 JSON 数据

std::string name = j["name"];   // "三三"
int age = j["age"];             // 20
std::string skill = j["skills"][0];  // "C++"

(2)检查键是否存在

if (j.contains("age")) {
    std::cout << "Age: " << j["age"] << std::endl;
}

(3)修改 JSON

j["age"] = 21;
j["skills"].push_back("Rust"); // 添加新技能
j["city"] = "Shanghai"; // 新增字段

3. JSON 转字符串(序列化)

(1)紧凑格式

std::string compact = j.dump();
std::cout << compact << std::endl;

输出:

{"name":"三三","age":21,"skills":["C++","Python","Go","Rust"],"city":"Shanghai"}

(2)美化格式(带缩进)

std::string pretty = j.dump(4); // 4 代表缩进空格数
std::cout << pretty << std::endl;

输出:

{
    "name": "三三",
    "age": 21,
    "skills": [
        "C++",
        "Python",
        "Go",
        "Rust"
    ],
    "city": "Shanghai"
}

4. JSON 解析(反序列化)

(1)从字符串解析 JSON

std::string jsonStr = R"({"name":"三三","age":20,"skills":["C++","Python"]})";
json parsed = json::parse(jsonStr);
std::cout << parsed["name"] << std::endl; // "三三"

(2)从文件读取 JSON

std::ifstream file("data.json");
json j;
file >> j;  // 直接流输入到 JSON 对象
file.close();

(3)写入 JSON 到文件

std::ofstream outFile("output.json");
outFile << j.dump(4); // 美化格式写入
outFile.close();

5. 遍历 JSON

(1)遍历对象

for (auto& [key, value] : j.items()) {
    std::cout << key << " : " << value << std::endl;
}

输出:

name : "三三"
age : 21
skills : ["C++","Python","Go","Rust"]
city : "Shanghai"

(2)遍历数组

for (auto& skill : j["skills"]) {
    std::cout << skill << std::endl;
}

输出:

C++
Python
Go
Rust

6. JSON 与 STL 容器互转

(1)STL 容器转 JSON

std::vector<int> nums = {1, 2, 3, 4, 5};
json j = nums;  // 直接转换
std::cout << j.dump() << std::endl;  // [1,2,3,4,5]

(2)JSON 转 STL 容器

std::vector<int> vec = j.get<std::vector<int>>();

(3)map 转 JSON

std::map<std::string, int> myMap = {{"A", 1}, {"B", 2}};
json j = myMap;
std::cout << j.dump() << std::endl;  // {"A":1,"B":2}

(4)JSON 转 map

std::map<std::string, int> parsedMap = j.get<std::map<std::string, int>>();

7. JSON 其他常用方法

方法说明
j.empty()检查 JSON 是否为空
j.size()获取 JSON 元素数量
j.clear()清空 JSON
j.erase("key")删除指定 key
j.is_object()是否为对象
j.is_array()是否为数组
j.is_string()是否为字符串
j.is_number()是否为数值

示例:

if (j.is_object()) {
    std::cout << "这是一个 JSON 对象" << std::endl;
}

总结

功能方法
创建 JSONjson j = {{"key", "value"}};
访问/修改 JSONj["key"]j["array"].push_back(value);
序列化 JSONj.dump()(紧凑格式)、j.dump(4)(美化格式)
解析 JSONjson::parse(str)
遍历 JSONfor(auto& [k, v] : j.items())
JSON 与 STL 互转json j = vec;std::map<std::string, int> m = j.get<std::map<std::string, int>>();

完整示例:C++ 使用 nlohmann/json

这个示例演示了 JSON 创建、访问、修改、序列化、反序列化、遍历、文件读写 等常见操作。


💻 示例代码

#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main() {
    // 1. 创建 JSON 数据
    json j;
    j["name"] = "三三";
    j["age"] = 20;
    j["skills"] = {"C++", "Python", "Go"};
    j["address"] = { {"city", "Shanghai"}, {"zip", "200000"} };

    // 2. 访问 JSON 数据
    std::cout << "Name: " << j["name"] << std::endl;
    std::cout << "Age: " << j["age"] << std::endl;
    std::cout << "First Skill: " << j["skills"][0] << std::endl;
    std::cout << "City: " << j["address"]["city"] << std::endl;

    // 3. 修改 JSON 数据
    j["age"] = 21;
    j["skills"].push_back("Rust");  // 添加新技能
    j["address"]["district"] = "Pudong";  // 添加新字段

    // 4. JSON 转字符串(序列化)
    std::string jsonString = j.dump(4); // 美化格式
    std::cout << "Serialized JSON:\n" << jsonString << std::endl;

    // 5. 写入 JSON 到文件
    std::ofstream outFile("output.json");
    if (outFile.is_open()) {
        outFile << jsonString;
        outFile.close();
    }

    // 6. 从字符串解析 JSON(反序列化)
    std::string jsonStr = R"({"status":"ok","message":"success","userId":123})";
    json parsedJson = json::parse(jsonStr);
    std::cout << "Parsed Message: " << parsedJson["message"] << std::endl;

    // 7. 从文件读取 JSON
    std::ifstream inFile("output.json");
    if (inFile.is_open()) {
        json readJson;
        inFile >> readJson;
        inFile.close();
        std::cout << "Read JSON from file:\n" << readJson.dump(4) << std::endl;
    }

    // 8. 遍历 JSON 对象
    std::cout << "Traversing JSON object:" << std::endl;
    for (auto& [key, value] : j.items()) {
        std::cout << key << " : " << value << std::endl;
    }

    return 0;
}

📌 代码解析

  1. 创建 JSON

    • j["name"] = "三三"; 直接赋值创建 JSON 数据
    • 嵌套对象 j["address"] = { {"city", "Shanghai"}, {"zip", "200000"} };
    • 数组 j["skills"] = {"C++", "Python", "Go"};
  2. 访问 & 修改 JSON

    • std::cout << j["name"]; 访问 JSON 数据
    • j["age"] = 21; 修改 JSON
    • j["skills"].push_back("Rust"); 动态添加数组元素
  3. 序列化 & 反序列化

    • std::string jsonString = j.dump(4); 转字符串(美化格式)
    • json parsedJson = json::parse(jsonStr); 解析 JSON
  4. 文件读写

    • std::ofstream outFile("output.json"); 写入文件
    • std::ifstream inFile("output.json"); 读取文件
  5. 遍历 JSON

    • for (auto& [key, value] : j.items()) 遍历 JSON

📌 运行结果

Name: 三三
Age: 20
First Skill: C++
City: Shanghai
Serialized JSON:
{
    "name": "三三",
    "age": 21,
    "skills": [
        "C++",
        "Python",
        "Go",
        "Rust"
    ],
    "address": {
        "city": "Shanghai",
        "zip": "200000",
        "district": "Pudong"
    }
}
Parsed Message: success
Read JSON from file:
{
    "name": "三三",
    "age": 21,
    "skills": [
        "C++",
        "Python",
        "Go",
        "Rust"
    ],
    "address": {
        "city": "Shanghai",
        "zip": "200000",
        "district": "Pudong"
    }
}
Traversing JSON object:
name : "三三"
age : 21
skills : ["C++","Python","Go","Rust"]
address : {"city":"Shanghai","zip":"200000","district":"Pudong"}

✅ 你学到了什么?

  1. json 创建、访问、修改
  2. dump() 序列化 & parse() 反序列化
  3. JSON 读写文件
  4. 遍历 JSON 数据

你可以直接复制这段代码,运行看看!🚀

<think>好的,我现在需要回答用户关于如何在C语言中解析和生成JSON的问题。首先,用户提到了他们知道cJSON和Jansson这两个,但想了解具体的方法。我需要整理这两个的基本用法、安装方法、解析和生成的步骤,以及性能优化和常见问题的解决方法。 首先,我应该先介绍这两个,说明它们的特点和适用场景。比如,cJSON更轻量,适合资源有限的环境;而Jansson功能更全面,适合复杂需求。然后,分步骤说明如何安装这两个,比如通过包管理器或者源码编译。 接下来是解析JSON的步骤。需要给出具体的代码示例,比如使用cJSON解析字符串、读取文件,以及错误处理的例子。同时,对于Jansson,也要展示类似的解析流程,强调类型检查和内存管理的重要性。 生成JSON的部分同样需要代码示例,比如创建对象、构建结构体,并转换为字符串。要比较cJSON和Jansson在生成JSON时的不同API设计,比如cJSON的链式调用和Jansson的类型安全函数。 然后,性能优化方面,可以提到重复使用对象、避免频繁内存分配、使用流式解析处理大文件等技巧。常见问题部分需要涵盖内存泄漏、类型转换错误和编码问题,给出解决方案,比如使用Valgrind检测内存泄漏,严格检查节点类型,处理UTF-8编码。 最后,生成相关问题,帮助用户深入理解,比如比较两个的优缺点,处理嵌套结构,或者解决内存管理问题。需要确保所有代码示例正确,符合LaTeX格式要求,并且引用用户提供的参考内容,比如引用[1]和[2]。 现在需要检查是否有遗漏的步骤,比如安装方法是否详细,代码示例是否正确,是否有提到错误处理和内存管理。还要确保回答结构清晰,分点明确,符合用户的要求。另外,注意使用中文,避免使用Markdown,行内公式用$...$,独立公式用$$...$$,但在这个回答中可能不需要太多数学公式,主要关注代码和文本结构。 可能需要注意的地方:用户提供的引用[1]和[2]是关于C语言解析JSON的基础和cJSON的介绍,要在回答中适当引用这些内容,例如在介绍cJSON时引用[2],在讨论解析JSON的重要性时引用[1]。此外,确保代码示例正确,比如cJSON的解析和生成代码是否与实际的用法一致,避免语法错误。 总结回答的结构应该是:引言、推荐的、安装方法、解析步骤、生成步骤、性能优化、常见问题、相关问题。每个部分都要简明扼要,提供代码示例和解释。确保所有信息准确,特别是的函数使用和内存管理部分,因为这是C语言中容易出错的地方。</think>### 如何在C语言中解析和生成JSON? 在C语言中解析和生成JSON需依赖第三方,以下是两种常用的详细方法: --- #### 一、推荐及特点 1. **cJSON** - 轻量级(单文件),适合嵌入式或资源受限环境[^2]。 - 简单易用,但需手动管理内存。 2. **Jansson** - 功能全面,支持复杂操作(如流式解析)[^1]。 - 类型安全,内存管理更自动化。 --- #### 二、安装方法 1. **cJSON** ```bash # Debian/Ubuntu sudo apt-get install libcjson-dev # 或源码编译 git clone https://github.com/DaveGamble/cJSON cd cJSON && make && sudo make install ``` 2. **Jansson** ```bash # Debian/Ubuntu sudo apt-get install libjansson-dev # 或源码编译 wget https://github.com/akheron/jansson/archive/refs/tags/v2.14.tar.gz tar -xzf v2.14.tar.gz && cd jansson-2.14 && mkdir build && cd build cmake .. && make && sudo make install ``` --- #### 三、解析JSON步骤(以cJSON为例) 1. **解析字符串** ```c #include <cJSON.h> const char *json_str = "{\"name\":\"Alice\", \"age\":30}"; cJSON *root = cJSON_Parse(json_str); if (root == NULL) { printf("解析失败: %s\n", cJSON_GetErrorPtr()); return; } cJSON *name = cJSON_GetObjectItem(root, "name"); cJSON *age = cJSON_GetObjectItem(root, "age"); printf("Name: %s, Age: %d\n", name->valuestring, age->valueint); cJSON_Delete(root); // 释放内存 ``` 2. **解析文件** ```c FILE *fp = fopen("data.json", "r"); fseek(fp, 0, SEEK_END); long len = ftell(fp); fseek(fp, 0, SEEK_SET); char *buffer = (char*)malloc(len + 1); fread(buffer, 1, len, fp); fclose(fp); cJSON *root = cJSON_Parse(buffer); free(buffer); // 需手动释放缓冲区 ``` --- #### 四、生成JSON步骤(以Jansson为例) ```c #include <jansson.h> json_t *root = json_object(); json_object_set_new(root, "name", json_string("Bob")); json_object_set_new(root, "age", json_integer(25)); // 添加数组 json_t *scores = json_array(); json_array_append_new(scores, json_integer(90)); json_array_append_new(scores, json_integer(85)); json_object_set_new(root, "scores", scores); // 转换为字符串 char *json_str = json_dumps(root, JSON_INDENT(4)); printf("%s\n", json_str); // 释放资源 free(json_str); json_decref(root); ``` --- #### 五、性能优化技巧 1. **重复利用对象**:避免频繁创建/销毁JSON对象,复用已有结构。 2. **减少内存分配**:预分配缓冲区,如使用`json_dumpb`(Jansson)避免多次拷贝。 3. **流式解析**:对大型JSON文件,使用Jansson的`json_load_callback`逐步读取。 --- #### 六、常见问题与解决 1. **内存泄漏** - 使用Valgrind检测未释放的JSON对象。 - cJSON需手动调用`cJSON_Delete()`,Jansson通过引用计数自动释放。 2. **类型错误** - 检查节点类型:`cJSON_IsNumber()`或`json_is_string()`。 3. **编码问题** - 确保输入为UTF-8,处理转义字符(如`\"`)。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值