简介
nlohmann::basic_json::at
是一个成员函数,用于访问 nlohmann::json
对象中的元素。这个函数提供了一种安全的方式来访问 JSON 对象的元素,如果试图访问不存在的元素,它会抛出一个类型为 nlohmann::json::out_of_range
的异常。
这个函数有两个版本:
-
T& at(KeyT&& key)
: 这个版本用于非常量 JSON 对象,返回一个指向指定键的元素的引用。如果元素不存在,它会抛出一个nlohmann::json::out_of_range
异常。 -
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'