• 2309json.nlohmann数格示例1


    参考

    示例

    下面是一些示例,可让你了解如何使用该类.
    除了以下示例之外,你可能还需要:
    ->检查文档
    ->浏览独立示例文件

    每个API函数(记录在API文档中)都有相应独立示例文件.如,emplace()函数有一个匹配的emplace.cpp示例文件.

    从文件中读取JSON

    json类提供了操作JSON值的API.要通过读取JSON文件创建json对象,请如下:

    #include 
    #include 
    using json = nlohmann::json;
    //...
    std::ifstream f("example.json");
    json data = json::parse(f);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    JSON文本创建json对象

    假设要按json对象硬编码,来创建此文本JSON值:

    {
      "pi": 3.141,
      "happy": true
    }
    
    • 1
    • 2
    • 3
    • 4

    有多种选择:

    //使用(原始)串文字和`json::parse`
    json ex1 = json::parse(R"(
      {
        "pi": 3.141,
        "happy": true
      }
    )");
    //使用用户定义的(原始)串字面
    using namespace nlohmann::literals;
    json ex2 = R"(
      {
        "pi": 3.141,
        "happy": true
      }
    )"_json;
    //使用初化器列表
    json ex3 = {
      {"happy", true},
      {"pi", 3.141},
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    JSON作为第一类数据类型

    假设要创建JSON对象

    {
      "pi": 3.141,
      "happy": true,
      "name": "Niels",
      "nothing": null,
      "answer": {
        "everything": 42
      },
      "list": [1, 0, 2],
      "object": {
        "currency": "USD",
        "value": 42.99
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    使用此库,可编写:

    //创建空结构(空)
    json j;
     //添加一个存储为双精的数字(注意j到对象的隐式转换)
     
    j["pi"] = 3.141;
    //添加存储为`bool`的布尔值
    j["happy"] = true;
    //添加存储为`std::string`的串
    j["name"] = "Niels";
    //通过传递`nullptr`添加另一个空对象
    j["nothing"] = nullptr;
    //在对象内添加对象
    j["answer"]["everything"] = 42;
    //添加存储为`std::vector`的数组(使用初化器列表)
    j["list"] = { 1, 0, 2 };
    //添加另一个对象(使用对的初化器列表)
    j["object"] = { {"currency", "USD"}, {"value", 42.99} };
    //相反,你也可写(与上面的`JSON`类似)
    json j2 = {
      {"pi", 3.141},
      {"happy", true},
      {"name", "Niels"},
      {"nothing", nullptr},
      {"answer", {
        {"everything", 42}
      }},
      {"list", {1, 0, 2}},
      {"object", {
        {"currency", "USD"},
        {"value", 42.99}
      }}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    注意,不需要"告诉"编译器要使用哪种JSON值类型.如果想明确,可用json::array()json::object()函数:

    //一个表示空数组的方法`[]`
    json empty_array_explicit = json::array();
    //表达空对象`{}`的方法
    json empty_object_implicit = json({});
    json empty_object_explicit = json::object();
     //一个表示键/值对`数组[["`货币`","`美元`"],["`值`",42.99]]`的方法
     
    json array_not_object = json::array({ {"currency", "USD"}, {"value", 42.99} });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    序化/反序化

    可附加_json串字面来创建JSON值(反序化):

    //从串字面创建对象
    json j = "{ \"happy\": true, \"pi\": 3.141 }"_json;
    //甚至更好的原始串文字
    auto j2 = R"(
      {
        "happy": true,
        "pi": 3.141
      }
    )"_json;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    注意,如果不附加_json后缀,则不会解析传递的串字面,而只是用作JSON的串值.也即

    json j = "{ \"happy\": true, \"pi\": 3.141 }";
    
    • 1

    只存储串"{"happy":true,"pi":3.141}"而不解析实际对象.如下引入串字面.

    using namespace nlohmann::literals;
    
    • 1

    上例也可用json::parse()显式表示:

    //显式解析
    auto j3 = json::parse(R"({"happy": true, "pi": 3.141})");
    
    • 1
    • 2

    还可取JSON值的串表示(序化):

    //显式转换为串`{"happy":true,"pi":3.141}`序化,通过缩进的空格量打印
    std::string s = j.dump();    //
    std::cout << j.dump(4) << std::endl;
    //`{"`快乐`":`真`,"`圆周率`":3.141}`
    
    • 1
    • 2
    • 3
    • 4

    注意序化和赋值间的区别:

    //在`JSON`值中存储串
    json j_string = "this is a string";
    //提取串值
    auto cpp_string = j_string.template get<std::string>();
    //提取串值(变量已存在,时替代)
    std::string cpp_string2;
    j_string.get_to(cpp_string2);
    //提取序化值(显式`JSON`序化)
    std::string serialized_string = j_string.dump();
    //原始串的输出
    std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.template get<std::string>() << '\n';
    //序化值的输出
    std::cout << j_string << " == " << serialized_string << std::endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    .dump()返回最初存储的串值.
    注意,该库仅支持UTF-8.在库中用不同编码存储串时,调用dump()可能会触发异常,除非json::error_handler_t::replacejson::error_handler_t::ignore用作错误处理器.

    传入/传出流(如文件,串流)

    还可用序化和反序化:

    //从标准输入反序化
    json j;
    std::cin >> j;
    //序化为标准输出
    std::cout << j;
    //`setw`机械手重载以设置漂亮的打印
    std::cout << std::setw(4) << j << std::endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这些操作符适合std::istreamstd::ostream的子类.下面是文件的相同示例:

    //读取`JSON`文件
    std::ifstream i("file.json");
    json j;
    i >> j;
    //修饰的`JSON`写入另一个文件
    std::ofstream o("pretty.json");
    o << std::setw(4) << j << std::endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    从迭代器区间读取

    你还可从迭代器区间解析JSON;也即,从迭代器可访问的容器中,其value_type1,24个字节的整数类型,解释分别为UTF-8,UTF-16UTF-32.
    如,std::vectorstd::list:

    std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
    json j = json::parse(v.begin(), v.end());
    
    • 1
    • 2

    可把迭代器保留在[开始,结束)区间:

    std::vector<std::uint8_t> v = {'t', 'r', 'u', 'e'};
    json j = json::parse(v);
    
    • 1
    • 2

    自定义数据源

    因为parse函数接受任意迭代器区间,因此你可通过实现LegacyInputIterator概念来提供自己的数据源.

    struct MyContainer {
      void advance();
      const char& get_current();
    };
    struct MyIterator {
        using difference_type = std::ptrdiff_t;
        using value_type = char;
        using pointer = const char*;
        using reference = const char&;
        using iterator_category = std::input_iterator_tag;
        MyIterator& operator++() {
            MyContainer.advance();
            return *this;
        }
        bool operator!=(const MyIterator& rhs) const {
            return rhs.target != target;
        }
        reference operator*() const {
            return target.get_current();
        }
        MyContainer* target = nullptr;
    };
    MyIterator begin(MyContainer& tgt) {
        return MyIterator{&tgt};
    }
    MyIterator end(const MyContainer&) {
        return {};
    }//开始,结束
    void foo() {
        MyContainer c;
        json j = json::parse(c);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    萨克斯接口

    有类似SAX的接口:

    //解析空值时调用
    bool null();
    //解析布尔值时调用;传递值
    bool boolean(bool val);
    //解析有符号或正整数时调用;传递值
    bool number_integer(number_integer_t val);
    bool number_unsigned(number_unsigned_t val);
    //解析浮点数时调用;传递值和原始串
    bool number_float(number_float_t val, const string_t& s);
    //解析串时调用;值被传递,可安全地移走
    bool string(string_t& val);
    //解析二进制值时调用;值被传递,可安全地移走
    bool binary(binary_t& val);
     //在对象或数组开始或结束时调用,或.传递元质数(如果不知道,则为`-1`)
    bool start_object(std::size_t elements);
    bool end_object();
    bool start_array(std::size_t elements);
    bool end_array();
    //解析对象键时调用;值被传递,可安全地移走
    bool key(string_t& val);
     //解析错误时调用;字节位置,最后令牌和异常被传递
     
    bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    每个函数的返回值确定是否应继续解析.
    要实现你自己的SAX处理器,请如下:

    0,在类中实现SAX接口.可用nlohmann::json_sax类作为基类,但也可用实现上述函数并公开的类.
    1,创建SAX接口类的对象,如my_sax.
    2,调用bool json::sax_parse(input, &my_sax),第一个参数可是输入,如串或输入流,第二个参数是指向SAX接口指针.
    3,注意,sax_parse函数仅返回一个布尔值,指示上次执行的SAX事件的结果.它不返回json值,由你决定如何处理SAX事件.

    此外,如果解析错误,不会触发异常,由你处理传递给parse_error实现的异常对象.内部,见json_sax.hpp文件.

    类似STL的访问

    按类似STL容器设计JSON类.事实上,它满足可逆容器要求.

    //使用`push_back`创建数组
    json j;
    j.push_back("foo");
    j.push_back(1);
    j.push_back(true);
    //也使用`emplace_back`
    j.emplace_back(1.78);
    //迭代数组
    for (json::iterator it = j.begin(); it != j.end(); ++it) {
      std::cout << *it << '\n';
    }
    //基于区间的
    for (auto& element : j) {
      std::cout << element << '\n';
    }
    //取置器
    const auto tmp = j[0].template get<std::string>();
    j[1] = 42;
    bool foo = j.at(2);
    //比较真其他东西4个项假`json::value_t::数组`数组又是空的方便的类型检查器
    j == R"(["foo", 1, true, 1.78])"_json;  //
    j.size();     //
    j.empty();    //
    j.type();     //
    j.clear();    //
    //
    j.is_null();
    j.is_boolean();
    j.is_number();
    j.is_object();
    j.is_array();
    j.is_string();
    //创建对象
    json o;
    o["foo"] = 23;
    o["bar"] = false;
    o["baz"] = 3.141;
    //也使用`Emplace`.
    o.emplace("weather", "sunny");
    //对象的特殊迭代器成员函数
    for (json::iterator it = o.begin(); it != o.end(); ++it) {
      std::cout << it.key() << " : " << it.value() << "\n";
    }
    //与区间相同的代码
    for (auto& el : o.items()) {
      std::cout << el.key() << " : " << el.value() << "\n";
    }
    //使用结构化绑定更加轻松`(C++17)`
    for (auto& [key, value] : o.items()) {
      std::cout << key << " : " << value << "\n";
    }
    //查找项
    if (o.contains("foo")) {
      //有个带有`"FOO"`键的项
    }
    //或通过查找和迭代器
    if (o.find("foo") != o.end()) {
      //有一个带有`"FOO"`键的项
    }
    //或使用`count()10`删除项更简单
    int foo_present = o.count("foo"); //
    int fob_present = o.count("fob"); //
    //
    o.erase("foo");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64

    STL容器转换

    序列容器(std::array,std::vector,std::deque,std::forward_list,std::list)都可来创建JSON数组(如,整数,浮点数,布尔值,串类型或本节中描述的STL容器)可来创建JSON数组.
    这同样适合类似的关联容器(std::set,std::multiset,std::unordered_set,std::unordered_multiset),但这时,数组元素的顺序根据元素在各个STL容器中的排序方式.

    std::vector<int> c_vector {1, 2, 3, 4};
    json j_vec(c_vector);
    //`[1,2,3,4]`
    std::deque<double> c_deque {1.2, 2.3, 3.4, 5.6};
    json j_deque(c_deque);
    //`[1.2,2.3,3.4,5.6]`
    std::list<bool> c_list {true, true, false, true};
    json j_list(c_list);
    //[真,真,假,真]
    std::forward_list<int64_t> c_flist {12345678909876, 23456789098765, 34567890987654, 45678909876543};
    json j_flist(c_flist);
    //`[12345678909876,23456789098765,34567890987654,45678909876543]`
    std::array<unsigned long, 4> c_array {{1, 2, 3, 4}};
    json j_array(c_array);
    //`[1,2,3,4]`
    std::set<std::string> c_set {"one", "two", "three", "four", "one"};
    json j_set(c_set); //只使用"一"的一个项`["`四`","`一`","`三`","`二`"]`
    //
    std::unordered_set<std::string> c_uset {"one", "two", "three", "four", "one"};
    json j_uset(c_uset); //"一"只使用一个项,也许`["`二`","`三`","`四`","`一`"]`
    //
    std::multiset<std::string> c_mset {"one", "two", "one", "four"};
    json j_mset(c_mset); //"一"的两个项都可能使用`["`一`","`二`","`一`","`四`"]`
    //
    std::unordered_multiset<std::string> c_umset {"one", "two", "one", "four"};
    json j_umset(c_umset); //"一"的两个项都可能使用`["`一`","`二`","`一`","`四`"]`
    //
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    同样,关联键值容器(std::map,std::multimap,std::unordered_map,std::unordered_multimap)的键可构造std::string,其值可来构造JSON值(见上例)都可来创建JSON对象.
    注意,在多重映射时,JSON对象中仅使用一个键,该值根据STL容器的内部顺序.

    std::map<std::string, int> c_map { {"one", 1}, {"two", 2}, {"three", 3} };
    json j_map(c_map);
    //`{"`一`":1,"`三`":3,"`二`":2}`
    std::unordered_map<const char*, double> c_umap { {"one", 1.2}, {"two", 2.3}, {"three", 3.4} };
    json j_umap(c_umap);
    //`{"`一`":1.2,"`二`":2.3,"`三`":3.4}`
    std::multimap<std::string, bool> c_mmap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
    json j_mmap(c_mmap); //只使用键"三"的一个项,也许`{"`一`":`真`,"`二`":`真`,"`三`":`真}
    //
    std::unordered_multimap<std::string, bool> c_ummap { {"one", true}, {"two", true}, {"three", false}, {"three", true} };
    json j_ummap(c_ummap); //只使用键"三"的一个项,也许`{"`一`":`真`,"`二`":`真`,"`三`":`真}
    //
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • 相关阅读:
    【Lattice FPGA 开发】IP核的调用
    64线LiDAR上速度可达120Hz!一种基于图像表示的快速精确的LiDAR地面分割算法
    微信在线点餐怎么做_怎么实现在微信公众号在线点餐
    语法基础(变量、输入输出、表达式与顺序语句完成情况)
    LLVM学习入门(1):Kaleidoscope语言及词法分析
    数据库实验三 数据查询一
    NAND闪存市场彻底复苏
    性能测试等级知识点
    计算机复试面试题总结
    ubuntu 给apt的apache2编译php7.1
  • 原文地址:https://blog.csdn.net/fqbqrr/article/details/133209937