Boost.JSON
综述
Boost.JSON
是一个可移植的C++库,提供了实现JavaScript Object Notation
或简称为JSON
(一种轻量级数据交换格式)的容器和算法。这种格式对人类来说很容易读写,对机器来说也很容易解析和生成。它基于JavaScript编程语言(Standard ECMA-262
)的子集。 JSON
是一种文本格式,与语言无关,但是使用C语言家族(包括C,C ++,C#,Java,JavaScript,Perl,Python等)的程序员熟悉的约定。这些属性使JSON
成为理想的数据交换语言。
该库着重于一个常见且流行的用例:在一个名为value的容器中进行解析和序列化,该容器保存JSON
类型。您生成的任何值都可以序列化然后反序列化,以确保结果将等于原始值。无论使用此库生成的任何JSON
输出,大多数常见的JSON
实现都可以用任何语言读取。
value
容器的设计使其非常适合作为词汇类型,适合在公共接口和库中使用,从而可以构成它们。该库将可表示的数据类型限制为大多数JSON
实现(尤其是JavaScript)几乎普遍接受的范围。解析器和序列化都具有很高的性能,可达到或超过最佳可比库的基准性能。分配器得到很好的支持。使用这些类型的代码将易于理解,灵活且高效。
Boost.JSON
提供以下功能:
- 快速编译
- 只需要C ++ 11
- 快速流解析器和序列化
- 常量时间复杂度的对象键查找
- 允许非标准
JSON
的选项 - 带有分配器支持的简单安全的现代API
- 不进行
Boost
编译,定义BOOST_JSON_STANDALONE
- 仅有头文件,无需链接到库
要求
支持的编译器
快速浏览
在这里,我们通过示例代码突出显示了重要的功能,以帮助传达接口的样式。 我们从包含库头文件开始,该文件将所有符号带入范围。 或者,可以包含各个头文件以获得特定类型的声明:
#include <boost/json.hpp>
为了链接您的程序,您将需要与内置库链接。 另外,您可以通过仅在所有新的或现有的源文件中包含此头文件来使用仅头文件配置:
#include <boost/json/src.hpp>
贯穿全文使用的示例代码和标识符的编写方式类似于以下声明:
#include <boost/json.hpp>
using namespace boost::json;
值
假设您要在容器中重新创建此JSON对象:
{
"pi": 3.141,
"happy": true,
"name": "Boost",
"nothing": null,
"answer": {
"everything": 42
},
"list": [1, 0, 2],
"object": {
"currency": "USD",
"value": 42.99
}
}
在此库中,数组,对象和字符串分别保存为JSON数组,对象和字符串,而类型value
是一个特殊的变体,可以容纳任何JSON元素。 在这里,我们构造一个空对象,然后插入上面的元素:
object obj; // construct an empty object
obj[ "pi" ] = 3.141; // insert a double
obj[ "happy" ] = true; // insert a bool
obj[ "name" ] = "Boost"; // insert a string
obj[ "nothing" ] = nullptr; // insert a null
obj[ "answer" ].emplace_object()["everything"] = 42; // insert an object with 1 element
obj[ "list" ] = { 1, 0, 2 }; // insert an array with 3 elements
obj[ "object" ] = { {"currency", "USD"}, {"value", 42.99} }; // insert an object with 2 elements
虽然键是字符串,但是对象的映射类型和数组的元素类型是一种称为value的特殊类型,可以容纳任何JSON元素,如先前的分配所示。 无需使用一系列函数调用来构建JSON文档,我们可以使用初始化列表在一个语句中构建它:
value jv = {
{ "pi", 3.141 },
{ "happy", true },
{ "name", "Boost" },
{ "nothing", nullptr },
{ "answer", {
{ "everything", 42 } } },
{"list", {1, 0, 2}},
{"object", {
{ "currency", "USD" },
{ "value", 42.99 }
} }
};
当从初始化列表中分配或构造值,数组或对象时,新值的创建仅发生一次。 这使初始化程序列表与使用其他方式创建值的效率相同。 该库中的类型是一等值(first-class),支持复制和移动构造以及分配:
array arr; // construct an empty array
arr = { 1, 2, 3 }; // replace the contents with 3 elements
value jv1( arr ); // this makes a copy of the array
value jv2( std::move(arr) ); // this performs a move-construction
assert( arr.empty() ); // moved-from arrays become empty
arr = { nullptr, true, "boost" }; // fill in the array again
Allocators
为了允许自定义内存分配策略,这些容器都允许使用storage_ptr
进行构造,该存储指针是指向memory_resource
的智能指针。 构造函数签名与其使用Allocator参数的std对等符具有相同的顺序。 一旦构造了容器,其内存资源就永远不会改变。 在这里,我们创建一个数组而不执行任何动态分配:
{
unsigned char buf[ 4096 ]; // storage for our array
static_resource mr( buf ); // memory resource which uses buf
array arr( &mr ); // construct using the memory resource
arr = { 1, 2, 3 }; // all allocated memory comes from `buf`
}
此库中的容器强制不变,即容器的每个元素都将使用相同的内存资源:
{
monotonic_resource mr; // memory resource optimized for insertion
array arr( &mr ); // construct using the memory resource
arr.resize( 1 ); // make space for one element
arr[ 0 ] = { 1, 2, 3 }; // assign an array to element 0
assert( *arr[0].storage() == *arr.storage() ); // same memory resource
}
当库类型用作pmr容器的元素类型时; 也就是说,使用polymorphic_allocator的容器,内存资源将自动传播到该类型及其所有子代:
{
monotonic_resource mr;
boost::container::pmr::vector< value > vv( &mr );
vv.resize( 3 );
// The memory resource of the container is propagated to each element
assert( *vv.get_allocator().resource() == *vv[0].storage() );
assert( *vv.get_allocator().resource() == *vv[1].storage() );
assert( *vv.get_allocator().resource() == *vv[2].storage() );
}