C++ JSON库 nlohmann::basic_json::at 的用法

简介

nlohmann::basic_json::at 是一个成员函数,用于访问 nlohmann::json 对象中的元素。这个函数提供了一种安全的方式来访问 JSON 对象的元素,如果试图访问不存在的元素,它会抛出一个类型为 nlohmann::json::out_of_range 的异常。

这个函数有两个版本:

  1. T& at(KeyT&& key): 这个版本用于非常量 JSON 对象,返回一个指向指定键的元素的引用。如果元素不存在,它会抛出一个 nlohmann::json::out_of_range 异常。

  2. const T& at(KeyT&& key) const: 这个版本用于常量 JSON 对象,返回一个指向指定键的元素的常量引用。如果元素不存在,它也会抛出一个 nlohmann::json::out_of_range 异常。

这里的 KeyT 是键的类型,对于 JSON 对象,它是一个字符串;对于 JSON 数组,它是一个大小类型的索引。

以下是一个使用 nlohmann::json::at 的例子:

#include <iostream>
#include <nlohmann/json.hpp>

int main() {
    // 创建一个 JSON 对象
    nlohmann::json j = {{"name", "John"}, {"age", 30}, {"city", "New York"}};

    try {
        // 使用 at() 访问元素
        std::string name = j.at("name");
        std::cout << "Name: " << name << std::endl;
    } catch (nlohmann::json::exception& e) {
        // 捕获并打印任何抛出的异常
        std::cout << "Exception: " << e.what() << std::endl;
    }

    return 0;
}

在这个例子中,我们创建了一个包含三个元素的 JSON 对象,然后使用 at() 函数来访问 “name” 键的元素。如果 “name” 键不存在,at() 函数会抛出一个异常,我们可以捕获这个异常并打印出错误信息。


nlohmann::basic_json::at 官网介绍

// (1)
reference at(size_type idx);
const_reference at(size_type idx) const;

// (2)
reference at(const typename object_t::key_type& key);
const_reference at(const typename object_t::key_type& key) const;

// (3)
template<typename KeyType>
reference at(KeyType&& key);
template<typename KeyType>
const_reference at(KeyType&& key) const;

// (4)
reference at(const json_pointer& ptr);
const_reference at(const json_pointer& ptr) const;

这个函数返回一个对指定位置 idx 的数组元素的引用,有边界检查。

返回一个对具有指定键 key 的对象元素的引用,有边界检查。

如果 KeyType 与 typename object_t::key_type 可比,并且 typename object_comparator_t::is_transparent 表示一种类型,那么这个重载就可用。

返回一个对指定 JSON 指针 ptr 指向的元素的引用,有边界检查。

模板参数

  • KeyType:除 json_pointer 之外的与 string_t 使用 object_comparator_t 可比的对象键的类型。这也可以是字符串视图(C++17)。

参数

  • idx(输入):要访问的元素的索引
  • key(输入):要访问的元素的对象键
  • ptr(输入):指向所需元素的 JSON 指针

返回值

  • 对索引 idx 处的元素的引用
  • 对键 key 处的元素的引用
  • 对键 key 处的元素的引用
  • 对 ptr 指向的元素的引用

异常安全性

强异常安全:如果发生异常,原始值保持不变。

异常

函数可能抛出以下异常:

  • 如果 JSON 值不是数组,则抛出 type_error.304;在这种情况下,使用索引调用 at 没有意义。参见下面的示例。
  • 如果索引 idx 超出数组的范围,即 idx >= size(),则抛出 out_of_range.401。参见下面的示例。

函数可能抛出以下异常:

  • 如果 JSON 值不是对象,则抛出 type_error.304;在这种情况下,使用键调用 at 没有意义。参见下面的示例。
  • 如果对象中没有存储键 key,即 find(key) == end(),则抛出 out_of_range.403。参见下面的示例。

参见 2。

函数可能抛出以下异常:

  • 如果传递的JSON指针PTR中的数组索引以‘0’开头,则引发parse_error.106。请参见下面的示例。
  • 如果传递的JSON指针PTR中的数组索引不是数字,则抛出parse_error.109。请参见下面的示例。
  • 如果传递的JSON指针ptr中的数组索引超出范围,则抛出out_of_range.401。请参见下面的示例。
  • 如果在传递的JSON指针PTR中使用数组索引‘-’,则抛出out_of_range.402。由于AT提供了经过检查的访问(并且没有隐式插入任何元素),因此索引‘-’总是无效的。请参见下面的示例。
  • 如果JSON指针描述了找不到的对象的键,则抛出out_of_range.403。请参见下面的示例。
  • 如果无法解析JSON指针PTR,则抛出Out_Of_range.404。请参见下面的示例。

复杂性

  • 一成不变。
  • 容器大小的对数。

示例

Example: (1) access specified array element with bounds checking

The example below shows how array elements can be read using at(). It also demonstrates the different exceptions that can be thrown.

#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create JSON array
    const json array = {"first", "2nd", "third", "fourth"};

    // output element at index 2 (third element)
    std::cout << array.at(2) << '\n';


    // exception type_error.304
    try
    {
        // use at() on a non-array type
        const json str = "I am a string";
        std::cout << str.at(0) << '\n';
    }
    catch (json::type_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // exception out_of_range.401
    try
    {
        // try to read beyond the array limit
        std::cout << array.at(5) << '\n';
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }
}

Output:

"third"
[json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.401] array index 5 is out of range

Example: (2) access specified object element with bounds checking

The example below shows how object elements can be read using at(). It also demonstrates the different exceptions that can be thrown.

#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

int main()
{
    // create JSON object
    const json object =
    {
        {"the good", "il buono"},
        {"the bad", "il cattivo"},
        {"the ugly", "il brutto"}
    };

    // output element with key "the ugly"
    std::cout << object.at("the ugly") << '\n';


    // exception type_error.304
    try
    {
        // use at() on a non-object type
        const json str = "I am a string";
        std::cout << str.at("the good") << '\n';
    }
    catch (json::type_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // exception out_of_range.401
    try
    {
        // try to read from a nonexisting key
        std::cout << object.at("the fast") << '\n';
    }
    catch (json::out_of_range)
    {
        std::cout << "out of range" << '\n';
    }
}

Output:

"il brutto"
[json.exception.type_error.304] cannot use at() with string
out of range

Example: (3) access specified object element using string_view with bounds checking

The example below shows how object elements can be read and written using at(). It also demonstrates the different exceptions that can be thrown.

#include <iostream>
#include <string_view>
#include <nlohmann/json.hpp>

using namespace std::string_view_literals;
using json = nlohmann::json;

int main()
{
    // create JSON object
    json object =
    {
        {"the good", "il buono"},
        {"the bad", "il cattivo"},
        {"the ugly", "il brutto"}
    };

    // output element with key "the ugly" using string_view
    std::cout << object.at("the ugly"sv) << '\n';

    // change element with key "the bad" using string_view
    object.at("the bad"sv) = "il cattivo";

    // output changed array
    std::cout << object << '\n';


    // exception type_error.304
    try
    {
        // use at() with string_view on a non-object type
        json str = "I am a string";
        str.at("the good"sv) = "Another string";
    }
    catch (json::type_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // exception out_of_range.401
    try
    {
        // try to write at a nonexisting key using string_view
        object.at("the fast"sv) = "il rapido";
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }
}
Output:


"il brutto"
{"the bad":"il cattivo","the good":"il buono","the ugly":"il brutto"}
[json.exception.type_error.304] cannot use at() with string
[json.exception.out_of_range.403] key 'the fast' not found
Example: (3) access specified object element using string_view with bounds checking
The example below shows how object elements can be read using at(). It also demonstrates the different exceptions that can be thrown.


#include <iostream>
#include <string_view>
#include <nlohmann/json.hpp>

using namespace std::string_view_literals;
using json = nlohmann::json;

int main()
{
    // create JSON object
    const json object =
    {
        {"the good", "il buono"},
        {"the bad", "il cattivo"},
        {"the ugly", "il brutto"}
    };

    // output element with key "the ugly" using string_view
    std::cout << object.at("the ugly"sv) << '\n';


    // exception type_error.304
    try
    {
        // use at() with string_view on a non-object type
        const json str = "I am a string";
        std::cout << str.at("the good"sv) << '\n';
    }
    catch (json::type_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // exception out_of_range.401
    try
    {
        // try to read from a nonexisting key using string_view
        std::cout << object.at("the fast"sv) << '\n';
    }
    catch (json::out_of_range)
    {
        std::cout << "out of range" << '\n';
    }
}

Output:

"il brutto"
[json.exception.type_error.304] cannot use at() with string
out of range

Example: (4) access specified element via JSON Pointer

The example below shows how object elements can be read and written using at(). It also demonstrates the different exceptions that can be thrown.

#include <iostream>
#include <nlohmann/json.hpp>

using json = nlohmann::json;
using namespace nlohmann::literals;

int main()
{
    // create a JSON value
    json j =
    {
        {"number", 1}, {"string", "foo"}, {"array", {1, 2}}
    };

    // read-only access

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

    // writing access

    // change the string
    j.at("/string"_json_pointer) = "bar";
    // output the changed string
    std::cout << j["string"] << '\n';

    // change an array element
    j.at("/array/1"_json_pointer) = 21;
    // output the changed array
    std::cout << j["array"] << '\n';


    // out_of_range.106
    try
    {
        // try to use an array index with leading '0'
        json::reference ref = j.at("/array/01"_json_pointer);
    }
    catch (json::parse_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.109
    try
    {
        // try to use an array index that is not a number
        json::reference ref = j.at("/array/one"_json_pointer);
    }
    catch (json::parse_error& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.401
    try
    {
        // try to use an invalid array index
        json::reference ref = j.at("/array/4"_json_pointer);
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.402
    try
    {
        // try to use the array index '-'
        json::reference ref = j.at("/array/-"_json_pointer);
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.403
    try
    {
        // try to use a JSON pointer to a nonexistent object key
        json::const_reference ref = j.at("/foo"_json_pointer);
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }

    // out_of_range.404
    try
    {
        // try to use a JSON pointer that cannot be resolved
        json::reference ref = j.at("/number/foo"_json_pointer);
    }
    catch (json::out_of_range& e)
    {
        std::cout << e.what() << '\n';
    }
}

Output:

1
"foo"
[1,2]
2
"bar"
[1,21]
[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'
[json.exception.parse_error.109] parse error: array index 'one' is not a number
[json.exception.out_of_range.401] array index 4 is out of range
[json.exception.out_of_range.402] array index '-' (2) is out of range
[json.exception.out_of_range.403] key 'foo' not found
[json.exception.out_of_range.404] unresolved reference token 'foo'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值