nlohmann/json学习使用及示例

nlohmann/json学习使用及示例

简介:

nlohmann/json是一个C++的JSON解析库,由nlohmann开发。
它支持C++11及更高版本,并且可以在多个平台上使用,包括Windows、Linux和macOS等。
nlohmann/json提供了一组简单易用的API,可以方便地将JSON数据转换为C++对象,也可以将C++对象序列化为JSON格式。

nlohmann/json的主要特点包括:

轻量级:只包含头文件,不需要链接额外的库文件。

简单易用:提供了类似于STL容器的API,可以方便地处理JSON数据。

高效性能:使用了现代C++的特性,如移动语义和模板元编程等,可以获得高效的性能。

兼容性强:支持多种JSON格式,包括RFC 8259、ECMA-404和JSON5等。

开源免费:nlohmann/json是开源的,使用MIT许可证,可以免费使用和修改。

nlohmann/json已经成为C++领域中最流行的JSON解析库之一,被广泛应用于各种C++项目中,包括游戏开发、Web应用开发、物联网等领域。

下载

开源地址

对于我们使用者来说,只需要引入json.hpp这一个文件,其中包含所有接口函数。
json.hpp文件在single_include/nlohmann目录下,我们只需要下载该文件即可

示例:

#include <iostream>
#include <fstream>
// #include <glog/logging.h>
#include <gflags/gflags.h>
#include "nlohmann/json.hpp"

using json = nlohmann::json;

void test0()
{
    auto config_json = json::parse(R"({"happy": true, "pi": 3.141})"); // 构建json对象
    std::cout << config_json << std::endl;                             // 输出json对象值
    return;
}

void test1()
{
    // 方式一:赋值构造
    json j1;
    j1["name"] = "LeBorn Jame";                                  // 字符串
    j1["number"] = 23;                                           // 整数
    j1["man"] = true;                                            // 布尔值
    j1["children"] = {"LeBorn Jr", "Bryce Maximus", "Zhuri"};    // 数组
    j1["behavior"]["funny"] = "gigigigigigi";                    // 对象中元素值
    j1["wife"] = {{"name", "Savannah Brinson"}, {"man", false}}; // 对象

    // 方式二:直接构造
    json j2 = {
        {"name", "LeBorn Jame"},
        {"number", 23},
        {"man", true},
        {"children", {"LeBorn Jr", "Bryce Maximus", "Zhuri"}},
        {"behavior", {{"funny", "gigigigigigi"}}},
        {"wife", {{"name", "Savannah Brinson"}, {"man", false}}}
    };

    std::cout << "j1: " << j1 << std::endl;
    std::cout << "j2: " << j2 << std::endl;
    return;
}

void test2()
{
    // 构建一个json对象hututu
    json hututu = {
        {"name", "hututu"},
        {"age", 18},
        {"gender", 'm'},
        {"score", 88.99},
        {"location", {"aaa", "bbb", "ccc"}},
    };
    // 方式一
    auto name = hututu["name"].get<std::string>(); // 获取“name”对应的value值,并转为string类型
    std::cout << "name = " << name << std::endl;
    std::cout << "type name = " << typeid(name).name() << std::endl;
    std::cout << "----------------------" << std::endl;
    // 方式二
    auto location0 = hututu["location"][0].get<std::string>();
    auto location1 = hututu["location"][1].get<std::string>();
    auto location2 = hututu["location"].at(2).get<std::string>();
    std::cout << "location0 = " << location0 << std::endl;
    std::cout << "location1 = " << location1 << std::endl;
    std::cout << "location2 = " << location2 << std::endl;
    return;
}

void test3()
{
    // 构建一个json对象animalArray
    json animalArray = {"cat", "dog"}; // 定义一个数组类型的json对象
    animalArray.push_back("pig");      // 添加元素
    animalArray.emplace_back("duck");  // C++11新方式添加元素,减少申请内存
    std::cout << "animalArray: " << animalArray << std::endl;
    // 使用is_array()函数判断对象类型,使用empty函数判断数量是否为空
    if (animalArray.is_array() && !animalArray.empty())
    {
        auto size = animalArray.size(); // 使用size函数获取元素数量
        std::cout << "animalArray size: " << size << std::endl;
        auto animalLast = animalArray.at(size - 1).get<std::string>();
        std::cout << "animalArray[size-1]: " << animalLast << std::endl;
        std::cout << "/--------------------/" << std::endl;
    }

    json animalObject = {{"kind", "dog"}, {"height", 50}}; // 定义一个对象类型的json对象
    animalObject.push_back({"color", "red"});              // 插入元素
    animalObject.erase("kind");                            // 删除键值
    std::cout << "animalObject: " << animalObject << std::endl;
    animalObject["height"] = 99; // 通过key修改value值
    // 判断是否含有某个键值方式一
    if (animalObject.contains("height")) // 通过contains函数判断是否包含某个key
    {
        auto height = animalObject["height"].get<double>();
        std::cout << "方式一:height: " << height << std::endl;
    }
    // 判断是否含有某个键值方式二
    auto size = animalObject.count("height"); // 通过count函数计算某一个键的数量
    if (size > 0)
    {
        std::cout << "方式二:存在height键值" << std::endl;
    }
    // 判断是否含有某个键值方式三
    auto iter = animalObject.find("height"); // 通过find函数查找某个键的迭代器
    if (iter != animalObject.end())
    {
        std::cout << "方式三:存在height键值" << std::endl;
    }
    // 遍历输出键值方式1
    std::cout << "遍历输出键值方式1:" << std::endl;
    for (auto item : animalObject.items())
    {
        std::cout << item.key() << " " << item.value() << std::endl;
    }
    // 遍历输出键值方式2
    std::cout << "遍历输出键值方式2:" << std::endl;
    for (auto iter = animalObject.begin(); iter != animalObject.end(); ++iter)
    {
        std::cout << iter.key() << " " << iter.value() << std::endl;
    }
    return;
}

void test4(){
    // 反序列化构建json对象,两种方式
    json hututu1 = "{\"name\":\"hututu\",\"age\":18,\"score\":88.99}"_json; // 方式1,通过"_json"实现反序列化
    auto temp = R"({"name":"hututu","age":18,"score":88.99})";              // 使用原生字符串关键字R来避免转移字符,但这一句并没有序列化,hututu2只保存字符串而已,需要结合方式3实现反序列化
    json hututu2 = json::parse(temp);                                       // 方式2,通过静态函数"parse"实现反序列化
    std::cout << "/----------反序列化-----------/" << std::endl;
    std::cout << "hututu1 = " << hututu1 << std::endl;
    std::cout << "hututu2 = " << hututu2 << std::endl;
    std::cout << "/----------序列化-----------/" << std::endl;
    // 序列化(Serialization):dump(number),number为打印出的空格数
    std::string hututu1_string = hututu1.dump(); // animal1值为{"kind":"dog","height":50}
    std::string hututu2_string = hututu2.dump(4);
    std::cout << "hututu1_string = " << hututu1_string << std::endl;
    std::cout << "hututu2_string = " << hututu2_string << std::endl;
    return;
}

void test5(std::string input,std::string output){
    // 从.json文件中读取内容到json对象中
    std::ifstream in(input); // 打开文件,关联到流in
    json hututu = {"111", "222"};      // 定义一个json对象为hututu,有初始内容,但是会被覆盖
    in >> hututu;                      // 从流in中(也就是./person.json文件)读取内容到json对象中,会覆盖之前内容
    in.close();                        // 关闭文件流in
    hututu["aaa"] = "bbb";             // 添加json对象内容
    std::cout << hututu << std::endl;            // 输出json对象值

    // 输出json对象内容到文件中,并生成新的文件
    std::ofstream out(output); // 创建文件./new.json,并关联到流out
    hututu["name"] = "new name";     // 更改hututu对象的内容
    out << std::setw(4) << hututu;   // 输出json对象hututu信息到文件./new.json中,std::setw(4)用于设置增加打印空格
    out.close();                     // 关闭文件流out
    return;
}

class Persion
{
  public:
    Persion()=default;
    Persion(std::string n,int a,double s):name(n),age(a),score(s){};
    void display()
    {
        std::cout << "person name = " << this->name << std::endl;
        std::cout << "person age = " << this->age << std::endl;
        std::cout << "person score = " << this->score << std::endl;
    }
    // 类名,成员1,成员2,成员3
    NLOHMANN_DEFINE_TYPE_INTRUSIVE(Persion, name, age, score);
  private:
    std::string name;
    int age;
    double score;
};

void test6(){
    Persion hututu{"hututu", 18, 88.99}; // 定义一个person对象为hututu
    std::cout << "/----------调用宏实现:to json-----------/" << std::endl;
    json j1 = hututu;
    std::cout << j1 << std::endl;
    std::cout << j1.dump() << std::endl;
    std::cout << "/----------调用宏实现:from json-----------/" << std::endl;
    j1["name"] = "new name";
    Persion hututu_new = j1;
    hututu_new.display();
    return;
}


void call_func(const std::function<void(void)> &f) { f(); }
void call_func1(std::string a, std::string b, const std::function<void(std::string, std::string)> &f) { f(a, b); }

DEFINE_int32(testfucnum, 0, "测试哪个test");
DEFINE_string(input,"./input.json","测试读取的json文件");
DEFINE_string(output,"./output.json","测试生成的json文件");

int main(int argc, char **argv)
{
    // Parsing command-line
    google::ParseCommandLineFlags(&argc, &argv, true);

    switch (FLAGS_testfucnum)
    {
    case 0: 
        call_func(test0);
        break;
    case 1: //两种方式创建json对象:赋值构造+直接构造
        call_func(test1);
        break;
    case 2: //由json对象得到basic value
        call_func(test2);
        break;
    case 3: //像操作stl container一样操作json value
        call_func(test3);
        break;
    case 4: //json序列化与反序列化
        call_func(test4);
        break;
    case 5: //json对象和文件输入输出转换
        call_func1(FLAGS_input,FLAGS_output,test5);
        break;
    case 6: //NLOHMANN_DEFINE_TYPE_INTRUSIVE宏的使用
        call_func(test6);
        break;
    default:
        break;
    }

    return 0;
}
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值