nlohmann/json 的使用

什么是json

json是一种文本规范 ,可以简单的表示树形结构 的数据,本质是一条字符串。

库的引入

cpp 复制代码
#include <nlohmann/json.hpp>
using json = nlohmann::json; // 简化命名(否则每次都要写nlohmann::json)

json 对象的创建与初始化

方式 1:空对象初始化(逐步赋值)

适合不确定初始数据,后续动态添加的场景:

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
int main() {
    json user;  // 创建空JSON对象 
    user["name"] = "张三";  // 新增字符串键值对
    user["age"] = 25;       // 新增整数键值对
    user["is_student"] = false;  // 新增布尔值
    user["hobbies"] = {"篮球", "编程"};  // 新增数组

    std::cout << "空对象逐步赋值结果:" << user << std::endl;return 0;}

方式 2:初始化列表(直接赋值)

最常用场景,一次性定义完整 JSON 结构,直观简洁:

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
int main() {// 直接用键值对列表初始化,支持嵌套
    json student = {
        {"name", "李四"},
        {"age", 20},
        {"scores", {{"math", 90}, {"english", 85}}},  // 嵌套对象
        {"hobbies", {"游泳", "阅读"}
    }                 // 嵌套数组};
    std::cout << "初始化列表创建结果:" << student << std::endl;return 0;}

方式 3:从 C++ 原生容器转换

支持vector(转 JSON 数组)和map(转 JSON 对象)直接转换:

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
#include <vector>
#include <map>
using json = nlohmann::json;
int main() {
    // vector → JSON数组
    std::vector<int> nums = {10, 20, 30, 40};
    json json_nums = nums;
    std::cout << "vector转JSON数组:" << json_nums << "\n\n";
    
    // map → JSON对象
    std::map<std::string, std::string> info = {{"city", "深圳"}, {"job", "程序员"}};
    json json_info = info;
    std::cout << "map转JSON对象:" << json_info << std::endl;return 0;}

方式 4:从 JSON 字符串解析

适合处理网络请求返回、配置文件内容等字符串格式 JSON:

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;
int main() {// 原生字符串R"()":避免双引号转义(无需写\")
    std::string json_str = R"(
        {
            "id": 1001,
            "name": "王五",
            "score": 98.5,
            "tags": ["优秀", "勤奋"]
        }
    )";
    // 解析字符串为JSON对象
    json from_str = json::parse(json_str);
    std::cout << "字符串解析结果:" << from_str << std::endl;return 0;}

json 数据的访问

方式1:at()方法

at(键)得到值

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
#include <stdexcept>  // 用于异常处理
using json = nlohmann::json;

int main() {
    json student = {
        {"name", "李四"},
        {"scores", {{"math", 90}}},
        {"hobbies", {"游泳", "阅读"}}
    };

    try {
        // 访问嵌套对象
        double math_score = student.at("scores").at("math");
        // 访问数组(索引从0开始)
        std::string hobby1 = student.at("hobbies").at(0);
        
        std::cout << "数学成绩:" << math_score << "\n";
        std::cout << "第一个爱好:" << hobby1 << "\n";
        
        // 访问不存在的键(触发异常)
        std::string gender = student.at("gender");
    } catch (const std::exception& e) {
        std::cout << "访问失败:" << e.what() << std::endl;
    }

    return 0;
}

方式 2:[]操作符

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    json student = {{"name", "李四"}, {"age", 20}};

    // 确定键存在时,直接访问
    std::string name = student["name"];
    int age = student["age"];
    std::cout << "姓名:" << name << ",年龄:" << age << "\n";

    // 访问不存在的键:自动创建空值(注意:这会修改原JSON)
    student["gender"];  // 新增key="gender",值为null
    std::cout << "误操作后的JSON:" << student << std::endl;

    return 0;
}

方式 3:value()方法

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    json student = {{"name", "李四"}, {"age", 20}};

    // 键存在:返回对应值
    std::string name = student.value("name", "未知姓名");
    // 键不存在:返回默认值25
    int age = student.value("age", 25);
    // 键不存在:返回默认值"男"
    std::string gender = student.value("gender", "男");

    std::cout << "姓名:" << name << ",年龄:" << age << ",性别:" << gender << std::endl;
    return 0;
}

json数据的修改

修改已有键值

直接用=赋值覆盖旧值

直接用[]赋值(即使键不存在)

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    json student = {{"name", "李四"}, {"age", 20}, {"scores", {{"english", 85}}}};

    // 修改普通键值
    student["age"] = 21;
    // 修改嵌套键值
    student["scores"]["english"] = 88;
    student["scores"]["math"] = 80;

    std::cout << "修改后:" << student << std::endl;
    return 0;
}

数组操作(添加 / 删除元素)

JSON 数组支持push_back()(添加)、erase()(删除)等操作:

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    json hobbies = {"游泳", "阅读"};

    // 数组末尾添加元素
    hobbies.push_back("跑步");
    std::cout << "添加后:" << hobbies << "\n";

    // 删除索引为1的元素(第二个元素)
    hobbies.erase(1);
    std::cout << "删除后:" << hobbies << "\n";

    // 获取数组长度
    std::cout << "数组长度:" << hobbies.size() << std::endl;

    return 0;
}

json 数据的序列化与反序列化

序列化:JSON 对象 → 字符串 / 文件(用于存储、网络传输);

dump()

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    json data = {
        {"name", "张三"},
        {"age", 25},
        {"hobbies", {"篮球", "编程"}}
    };

    // 紧凑格式(无缩进,适合传输/存储)
    std::string compact_str = data.dump();
    std::cout << "紧凑格式:" << compact_str << "\n\n";

    // 带缩进格式(4个空格,易读,适合日志/配置文件)
    std::string pretty_str = data.dump(4);
    std::cout << "带缩进格式:\n" << pretty_str << std::endl;

    return 0;
}

反序列化:字符串 / 文件 → JSON 对象(用于解析数据)。

parse()

cpp 复制代码
#include <nlohmann/json.hpp>
#include <iostream>
using json = nlohmann::json;

int main() {
    // 模拟网络请求返回的JSON字符串
    std::string response_str = R"({"code": 200, "msg": "success", "data": {"user_id": 1001}})";

    // 解析字符串
    json response = json::parse(response_str);

    // 访问解析后的数据
    int code = response["code"];
    std::string msg = response["msg"];
    int user_id = response["data"]["user_id"];

    std::cout << "状态码:" << code << "\n";
    std::cout << "信息:" << msg << "\n";
    std::cout << "用户ID:" << user_id << std::endl;

    return 0;
}

多层参数访问

cpp 复制代码
std::string city = data["user"]["info"]["address"]["city"];
std::string city = data.at("user").at("info").at("address").at("city");
相关推荐
蓁蓁啊2 小时前
C/C++编译链接全解析——gcc/g++与ld链接器使用误区
java·c语言·开发语言·c++·物联网
D_evil__2 小时前
【Effective Modern C++】第四章 智能指针:19. 对于共享资源使用共享指针
c++
czxyvX3 小时前
016-二叉搜索树(C++实现)
开发语言·数据结构·c++
阿猿收手吧!3 小时前
【C++】volatile与线程安全:核心区别解析
java·c++·安全
Trouvaille ~3 小时前
【Linux】网络编程基础(三):Socket编程预备知识
linux·运维·服务器·网络·c++·socket·网络字节序
-dzk-3 小时前
【代码随想录】LC 707.设计链表
数据结构·c++·算法·链表
txinyu的博客4 小时前
解析muduo源码之 Buffer.h & Buffer.cc
c++
阿猿收手吧!4 小时前
【C++】异常处理:catch块执行后程序如何继续
服务器·网络·c++
代码游侠4 小时前
C语言核心概念复习(一)
c语言·开发语言·c++·笔记·学习