[C++]-JSON库nlohmann简介

文章目录

  • nlohmann库
    • 声明与构造
      • object生成
      • array生成
    • 解析与序列化
    • 获取与修改
      • value
      • 是否存在contains
      • 查找find
    • flatten
    • items
    • 类型判断
    • 结构体json
  • 示例

nlohmann/json 是一个用于解析json的开源c++库,使用方便直观。

nlohmann库

nlohmann库(https://github.com/nlohmann/json)提供了丰富而且符合直觉的接口(https://json.nlohmann.me/api/basic_json/),只需导入头文件即可使用,方便整合到项目中。

声明与构造

可声明普通json、数组或对象:

json j1;
json j2 = json::object();
json j3 = json::array();

也可直接构造(通过_json字面量,可以JSON格式直接构造出):

json j = R"(
{
    "name": "Mike",
    "age": 15,
    "score": 85.5
}
)"_json;

json j{
    { "name", "Mike"},
    { "age", 15 },
    { "score", 85.5}
};

object生成

object可通过key-value方式赋值,或通过push_back添加:

// example for an object
json j_object = {{"one", 1},
                 {"two", 2}};
j_object["three"] = 3;
j_object.push_back({"four",4});

std::cout<

array生成

数组可通过json::array()或声明初始化构造;

json j_array = {1, 2, 4};
j_array.push_back(8);
j_array.emplace_back(16);

std::cout<

解析与序列化

从字符串中解析:

auto j = json::parse(str);
// ...
// 序列化为字符串
std::string out = j.dump();

从文件中解析:

json j;
std::ifstream("c:\\test.json") >> j;
// ...
// 序列化到文件
std::ofstream("c:\\test.json") << j;

获取与修改

可通过at或者operator[]的方式获取元素的引用;然后通过get()来获取其值,直接赋值可修改其内容:

  • at返回对象的引用,当不存在时会抛出异常(out_of_range或parse_error):
    • at(key):根据下标获取数组元素;
    • at(index):根据键获取对象元素;
    • at(jsonPtr):根据路径获取对象元素;
  • operator[]与at类似,不存在时可能会自动添加null元素,而非抛出异常
void jsonAt() {
    json j = {
            {"number", 1},
            {"string", "foo"},
            {"array",  {1, 2}}
    };
    std::cout << j << '\n';

    std::cout << j.at("/number"_json_pointer) << '\n';
    std::cout << j.at("/string"_json_pointer) << '\n';
    std::cout << j.at("/array"_json_pointer) << '\n';
    std::cout << j.at("/array/1"_json_pointer) << '\n';

    auto ary = j.at("array");
    std::cout<();
    auto str = j.at("string").get();
    std::cout<

value

可通过value(key, defVal)来获取元素,当不存在时返回默认值;但不能类型冲突(即,defValue的类型与key对应元素的类型不匹配时,会抛出type_error异常):

void jsonValue() {
    json j = {
            {"integer",  1},
            {"floating", 42.23},
            {"string",   "hello world"},
            {"boolean",  true},
            {"object",   {{"key1", 1}, {"key2", 2}}},
            {"array",    {1, 2, 3}}
        };

    // access existing values
    int v_integer = j.value("integer", 0);
    double v_floating = j.value("floating", 0.0);

    // access nonexisting values and rely on default value
    std::string v_string = j.value("nonexisting", "[none]");
    bool v_boolean = j.value("nonexisting", false);

    // output values
    std::cout << std::boolalpha << v_integer << " " << v_floating
              << " " << v_string << " " << v_boolean << "\n";
}

// 1 42.23 [none] false

是否存在contains

通过contains可判断元素是否存在:

  • contains(key):根据键判断;
  • contains(jsonPtr):根据路径判断(对于数组,若索引不是数字会抛出异常);

查找find

查找指定的键(返回iterator):iterator find(key),通过*it获取其值;

void jsonFind() {
    // create a JSON object
    json j_object = {{"one", 1},
                     {"two", 2}};

    // call find
    auto it_two = j_object.find("two");
    auto it_three = j_object.find("three");

    // print values
    std::cout << std::boolalpha;
    std::cout << "\"two\" was found: " << (it_two != j_object.end()) << '\n';
    std::cout << "value at key \"two\": " << *it_two << '\n';
    std::cout << "\"three\" was found: " << (it_three != j_object.end()) << '\n';
}

flatten

basic_json flatten()可扁平化所有键(全部展开成一层key-value,key为对应的路径),通过unflatten可反扁平化:

void jsonFlatten() {
    // create JSON value
    json j = {{"pi",      3.14},
              {"happy",   true},
              {"name",    "Niels"},
              {"nothing", nullptr},
              {"list",    {1, 2, 3}},
              {"object",  {{"currency", "USD"}, {"value", 42.99}}}
            };

    // call flatten()
    std::cout << j.dump(2) <<'\n';
    std::cout << std::setw(4) << j.flatten() << '\n';
}

// {
//   "happy": true,
//   "list": [
//     1,
//     2,
//     3
//   ],
//   "name": "Niels",
//   "nothing": null,
//   "object": {
//     "currency": "USD",
//     "value": 42.99
//   },
//   "pi": 3.14
// }
// {
//     "/happy": true,
//     "/list/0": 1,
//     "/list/1": 2,
//     "/list/2": 3,
//     "/name": "Niels",
//     "/nothing": null,
//     "/object/currency": "USD",
//     "/object/value": 42.99,
//     "/pi": 3.14
// }

items

通过items可循环获取所有元素:

void jsonItems(){
    // create JSON values
    json j_object = {{"one", 1}, {"two", 2}};
    json j_array = {1, 2, 4, 8, 16};

    // example for an object
    for (auto& x : j_object.items())
    {
        std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
    }

    // example for an array
    for (auto& x : j_array.items())
    {
        std::cout << "key: " << x.key() << ", value: " << x.value() << '\n';
    }
}

类型判断

通过is_*判断元素所属类型:

  • is_array:是数组
  • is_object:是对象
  • is_null:为空
  • is_number:是数字(可继续细化is_number_float/is_number_integer/is_number_unsigned
  • is_boolean:是布尔类型
  • is_string:是字符串
  • is_prmitive:是简单类型(非数组与对象);
  • is_strucctured:数组或对象;

结构体json

通过在结构体所在的命名空间中创建void from_json(const json& j, MyStruct& p)可方便地从json中反序列化出结构体;而通过void to_json(json &j, const MyStruct& p)可方便地把结构体序列化为json;

通过get_to可把元素值赋值给类型兼容的变量:

namespace nj {
    struct Asset {
        std::string name;
        int value;
    };

    void to_json(json &j, const Asset &a) {
        j = json{{"name",  a.name},
                 {"value", a.value}};
    }

    void from_json(const json &j, Asset &a) {
        j.at("name").get_to(a.name);
        j.at("value").get_to(a.value);
    }
}

示例

json构造与操作的示例:

void jsonBuild() {
    // {
    //  "pi": 3.141,
    //  "happy": true,
    //  "name": "Niels",
    //  "nothing": null,
    //  "answer": {
    //    	"everything": 42
    //  },
    //  "list": [1, 0, 2],
    //  "object": {
    //	    "currency": "USD",
    // 	    "value": 42.99
    //  }
    //}
    json jData;
    jData["pi"] = 3.141;
    jData["happy"] = true;
    jData["name"] = "Niels";
    jData["nothing"] = nullptr;
    jData["answer"]["everything"] = 42; // 初始化answer对象
    jData["list"] = {1, 0, 2};     // 使用列表初始化的方法对"list"数组初始化
    jData["money"] = {{"currency", "USD"},
                      {"value",    42.99}}; // 初始化object对象

    std::cout << std::boolalpha;
    std::cout << jData << std::endl;
    std::cout << jData.at("pi") << std::endl;
    std::cout << jData["pi"].get() << std::endl;
    std::cout << jData["none"].is_null() << std::endl;
//    std::cout << jData.at("notAt") << std::endl; // throw exception
    std::cout << (jData.find("notFound") != jData.end()) << std::endl;
    std::cout << jData.contains("notContain") << std::endl;
    std::cout << jData.value("notExist", 0) << std::endl;

    std::cout << "sub-object" << std::endl;
    std::cout << jData.at("money") << std::endl;
    std::cout << jData.contains("currency") << std::endl;

    auto str = jData.dump(2);
    std::cout << "JSON OUT: \n";
    std::cout << str << std::endl;
//    std::cout <

以上示例可看出:

  • 通过operator[]获取不存在的key时,会添加一个值为null的键值对;
  • 通过at获取不存在的key时,会抛出异常;
  • 通过contains与find可判断元素是否存在;
  • 通过value获取存在,但类型与默认值不一致的元素时,会抛出异常;

你可能感兴趣的:(C/C++,c++,json)