nlohmann json库入门

nlohmann json的用法

nlohmann/json 是一个强大且易用的 C++ 库,用于处理 JSON 数据。它支持 JSON 格式与 C++ 数据结构之间无缝转换。

用法

github地址nlohmann/json: JSON for Modern C++ (github.com)
下载 https://github.com/nlohmann/json/tree/develop/include 下的nlohmann 目录,将其放到你项目的include目录下,在你需要使用的代码中 #include “nlohmann/json.hpp” 即可。

示例代码

# 目录结构
--nlohmann_json
----include/
------nlohmann/
--------json.hpp
--------other_files...
----build/
------test.json
------test0.json
------test1.json
----CMakeLists.txt
----nlohmann.json
----test_json.cpp

用法都放在下面的代码里。

#include <iostream>
#include <fstream>
#include <deque>
#include <set>
#include "nlohmann/json.hpp"


using njson = nlohmann::json;    // using作用是为nlohmann::json类型创建别名
using ordered_njson = nlohmann::ordered_json;
/*默认情况下,nlohmann::json 使用 std::map 存储对象字段,
  std::map 会按照键的字母顺序排序。如果不想对字段名进行排序,
  可以改用 nlohmann::json 提供的 ordered_json 类型,
  内部使用 std::unordered_map 来保持字段插入的顺序。
  ordered_json的dump()函数,不会调整字段的顺序;
  json的dump()函数,会按照字母顺序调整字段的顺序;
*/

namespace ns
{
    struct guy{
        int age;
        std::string name;
        // std::array<int, 5> array;
        int array[5];
    };    
}

namespace ns2
{
    struct guy2{
        int age;
        std::string name;
    };

    void to_json(njson& j, const guy2& g)
    {
        j = njson{{"age", g.age}, {"name", g.name}};
    }

    void from_json(const njson& j, guy2& g)
    {
        j.at("age").get_to(g.age);
        j.at("name").get_to(g.name);
    }

    // to_json 和 from_json 在nlohmann::json中就定义了,这里相当于根据实际数据结构重载了一下
    // 这里应该使用at(), 当读取不存在的字段时,它会抛出错误
}
    


using namespace std;

int main()
{
    njson j;

    j["username"] = "admin";
    j["password"] = "admin123";
    j["age"] = 24;
    j["balance"] = 1009999.99;
    j["married"] = false;
    j["nothing"] = NULL;    //nullptr
    j["list"] = {0, 1, 2, 3};
    j["object"] = {{"currency", "RMB"}, {"weight", 75}};
    j["answer"]["number"] = 42;
    j["answer"]["color"] = "black";
    //j.at("") == j[""] 使用at(), 当读取不存在的字段时,会抛出错误
    
    // std::string name_val = "val";	// name_val的值是一个变量
    // j[val] = 1;	// 若val变量的值对应的字段存在,则更新对应值,反之创建这个字段,写入值;
    // j.at(val) = 1; 就不行,若该字段不存在,会报错std::out_of_range, 它是只读操作,不能用来赋值;

#if 0
    // 新建nlohmann::json对象, 输出json信息
    ofstream put_file("test.json");
    // put_file << j << endl;
    put_file << j.dump(4) << endl;
    // cout << j.dump(4) << endl;
#endif

#if 0
    // 从nlohmann::json中获取相关json元素的值
    float balance = j.at("balance");
    float balance2 = (&j)->at("balance");
    float balance3 = j["balance"];
    cout << balance << " " << balance2 << " " << balance3 << endl;

    string username = j.at("username");
    cout << username << endl;

    for (const auto ele : j.at("list"))
    {
        cout << ele << " ";
    }
    cout << endl;
    for (int i = 0; i < 4; i ++)
    {
        cout << j.at("list").at(i) << " ";
    }
    cout << endl;

    cout << j.at("object").at("weight") << endl;
#endif

#if 0
    // string的反序列化,字符串转成nlohmann::json对象
    njson j2 = "{\"married\":true, \"age\":24}"_json;
    cout << j2.dump(4) << endl;
    auto j3 = R"({"married":true, "age":24})"_json;
    cout << j3.dump(4) << endl;

    // or
    string str = "{\"married\":false, \"age\":18}";
    auto j4 = njson::parse(str.c_str());
    cout << j4.dump() << endl;

    // string的序列化,nlohmann::json对象转成字符串
    string str2 = j4.dump();
    cout << str2 << endl;

    string s1 = "Hello, World";
    njson js1 = s1;
    // 推荐
    auto s2 = js1.get<std::string>();
    // 不推荐
    // string s3 = js1;
    cout << js1.dump() << endl;
    cout << s2 << endl;



#endif

#if 0
    //文件操作
    ifstream get_file("../nlohmann.json");
    if (!get_file.is_open())
    {
        cerr << "failed to op json file !" << endl;
        return -1;
    }
    stringstream buffer;
    buffer << get_file.rdbuf();
    string json_str = buffer.str();

    njson j5 = njson::parse(json_str.c_str());
    j5.at("married") = true;
    cout << j5.dump(4) << endl;
    ofstream put_file0("test0.json");
    put_file0 << j5.dump(4) << endl;

    ordered_njson j6 = ordered_njson::parse(json_str.c_str());
    j6.at("married") = true;
    cout << j6.dump(4) << endl;
    ofstream put_file1("test1.json");
    put_file1 << j6.dump(4) << endl;

    // or
    // ifstream get_file2("../nlohmann.json");
    // njson j7;
    // get_file2 >> j7;
    // cout << j7.at("age") <<endl;

#endif

#if 0
    // 任意类型转换
    ns::guy boy{24, "Rekko", {6,5,4,3,2}};
    // or
    // ns::guy boy = {24, "Rekko", {6,5,4,3,2}};
    njson j8;
    // the wrong usage:
    // j8.at("age") = boy.age;
    // j8.at("name") = boy.name;
    // j8.at("array") = boy.array;
    j8["age"] = boy.age;
    j8["name"] = boy.name;
    j8["array"] = boy.array;
    cout << j8.dump(4) <<endl;


    ns::guy girl {
        j8["age"].get<int>(),
        j8["name"].get<std::string>(),
        // j8["array"].get<std::array<int, 5>>(),
    } ;

    auto json_array = j8["array"];
    if (json_array.size() == 5)
    {
        for (size_t i = 0; i < 5; i++)
        {
            girl.array[i] = json_array[i].get<int>();
        }
    }
    else
    {
        cerr << "json array size is not right" <<endl;
    }
    cout << girl.age << " " << girl.name << endl;
    for (auto i : girl.array)
    {
        cout << i << " ";
    }
    cout << endl;

#endif

#if 0
    // 快速转换
    ns2::guy2 man = {30, "Alen"};
    njson j9 = man;
    cout << j9.dump() << endl;

    auto man2 = j9.get<ns2::guy2>();
    cout << man2.age << " " << man2.name << endl;

    assert(j9 == man2);
#endif

#if 0
    // 转换到二进制
    // json虽很常用,但它是非紧凑格式,不利于网络传输,或写入文件
    // nlohmann库 支持很多种二进制格式,包括了bson, cbor, messagepack, ubjson, bjdata
    njson jb = R"({"city": "shanghai", "school": "tongji"})"_json;

    // json to bson
    std::vector<std::uint8_t> b_bson = njson::to_bson(jb);
    // bson to json
    njson j_from_bson = njson::from_bson(b_bson);


    // json to cbor
    std::vector<std::uint8_t> b_cbor = njson::to_cbor(jb);
    // cbor to json
    njson j_from_cbor = njson::from_cbor(b_cbor);


    // json to messagepack
    std::vector<std::uint8_t> b_msgpack = njson::to_msgpack(jb);
    // messagepack to json
    njson j_from_b_msgpack = njson::from_msgpack(b_msgpack);


    // json to ubjson
    std::vector<std::uint8_t> b_ubjson = njson::to_ubjson(jb);
    // ubjson to json
    njson j_from_ubjson = njson::from_ubjson(b_ubjson);


    // json to bjdata
    std::vector<std::uint8_t> b_bjdata = njson::to_bjdata(jb);
    // bjdata to json
    njson j_from_bjdata = njson::from_bjdata(b_bjdata);

    cout << jb.dump() << endl;
    cout << j_from_bson.dump() << endl;
    cout << j_from_cbor.dump() << endl;
    cout << j_from_b_msgpack.dump() << endl;
    cout << j_from_ubjson.dump() << endl;
    cout << j_from_bjdata.dump() << endl;

    ofstream out_bson("bson.bin", std::ios::out | std::ios::binary);
    out_bson.write(reinterpret_cast<const char*>(b_bson.data()), b_bson.size() * sizeof(uint8_t));
    out_bson.close();

    ifstream in_bson("bson.bin", std::ios::in | std::ios::binary);
    std::vector<uint8_t> b_buffer((std::istreambuf_iterator<char>(in_bson)), std::istreambuf_iterator<char>());
    in_bson.close();
    njson j_from_bson_file = njson::from_bson(b_buffer);
    cout << j_from_bson_file.dump(4) << endl;
#endif

#if 0
    /*
    nlohmann 库支持从 STL 的任意序列容器初始化获得 json 对象(std::array, std::vector, std::deque, std::forward_list, std::list),
    它们的值可以被用来构造 json 的值。
    */
    /*
    std::set, std::multiset, std::unordered_set, std::unordered_multiset关联容器也具有同样的用法,
    并且也会保存其内在的顺序。
    */
    /*
    另外像std::map, std::multimap, std::unordered_map, std::unordered_multimap,nlohmann 也是支持的,
    但是需要注意的是其中的 Key 被构造为 std::string 保存。    
    */
    std::vector<int> d_vector {6, 5, 4, 3, 2, 1};
    njson j_vector(d_vector);
    cout << j_vector.dump(4) << endl;

    std::deque<double> d_deque {6.01, 5.02, 4.03};
    njson j_deque(d_deque);
    cout << j_deque.dump(4) << endl;

    std::array<int, 3> d_array {0, 1, 2};
    njson j_array(d_array);
    cout << j_array.dump(4) << endl;


    std::set<std::string> d_set {"one", "two", "three"};
    njson j_set(d_set);
    cout << j_set.dump(4) << endl;


    std::map<std::string, int> d_map {{"age", 24}, {"weight", 75}};
    njson j_map(d_map);
    cout << j_map.dump(4) << endl;
#endif

#if 1
    // nlohmann::json::array() 是一个静态方法,
    // 用于创建一个 JSON 类型的空数组或初始化为指定值的数组。
    njson j_array = njson::array();
    cout << j_array.dump() << endl;
    // []

    njson j_array2 = njson::array({1, 2.01, "Rekko", true, {0, 1}});
    cout << j_array2.dump() << endl;
    // [1,2.01,"Rekko",true,[0,1]]

    int age = 24;
    int weight = 75;
    int height = 175;
    njson j_array3 = njson::array();
    for (int i = 0; i < 3; i++)
    {
        njson j;
        j["age"] = age++;
        j["weight"] = weight++;
        j["height"] = height++;
        j_array3.push_back(j);
    }
    cout << j_array3.dump(4) << endl;

    njson j_array4;
    j_array4["changes"] = j_array3;
    cout << j_array4.dump(4) << endl;
#endif

    return 0;
}

参考文章:【C++ JSON 开源库】nlohmann入门使用总结 - fengMisaka - 博客园 (cnblogs.com)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值