////
Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
Copyright (c) 2025 Dmitry Arkhipov (grisumbras@yandex.ru)

Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

Official repository: https://github.com/boostorg/json
////

[#dom_value]
= `value` JSON文档在内存中表示为&lt;<ref_value>&gt;的实例：一种{req_Regular}类型，满足{req_DefaultConstructible}、{req_CopyConstructible}、{req_CopyAssignable}、{req_MoveConstructible}、{req_MoveAssignable}以及许多分配器感知容器的要求。它在内部实现为一个https://en.wikipedia.org/wiki/Tagged_union[__variant__]（变体），并且可以动态存储六种已定义的JSON值类型中的任意一种：</ref_value>

* **空值**：一种
https://en.cppreference.com/w/cpp/utility/variant/monostate[__monostate__]（单态）值，等同于`nullptr`。

* **布尔值**：布尔类型，取值为`true`或`false`。

* **数值**：整型或浮点型值。

* **字符串**：由零个或多个Unicode字符组成的序列，
类似于{std_string}。

* **数组**：值的有序列表，类似于{std_vector}。

* **对象**：名称/值对的集合，也称为
https://en.wikipedia.org/wiki/Associative_array[__关联数组__]。

== 处理值
从`nullptr`构造或默认构造的 &lt;<ref_value>&gt; 表示一个空的JSON元素：</ref_value>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_1,indent=0]
----

成员函数&lt;<ref_value_kind,`value::kind`>&gt;可用于查询值中存储的种类。或者，也可以使用诸如&lt;<ref_value_is_object,`value::is_object`>&gt;、&lt;<ref_value_is_number,`value::is_number`>&gt; 等成员函数来检查值是否为特定种类：</ref_value_is_number,`value::is_number`></ref_value_is_object,`value::is_object`></ref_value_kind,`value::kind`>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_2,indent=0]
----

诸如 &lt;<ref_value_if_object,`value::if_object`>&gt; 的函数在值为对象时返回指向该对象的指针，否则返回空指针。这使得它们既可用于上述的布尔上下文，也可用于赋值或条件表达式中，以捕获指针的值：</ref_value_if_object,`value::if_object`>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_3,indent=0]
----

&lt;<ref_value>&gt; 构造之后，其类型可根据赋值内容或通过调用&lt;<ref_value_emplace_array,`value::emplace_array`>&gt; 或 &lt;<ref_value_emplace_bool,`value::emplace_bool`>&gt; 等函数来改变。如果赋值成功，即未引发任何异常，则该值将被替换。否则，原值保持不变。所有可能修改值失败的操作均提供强异常安全保证。</ref_value_emplace_bool,`value::emplace_bool`></ref_value_emplace_array,`value::emplace_array`></ref_value>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_4,indent=0]
----

下表列出了所有用于判断和访问 &lt;<ref_value>&gt; 内容的方法：</ref_value>

.&lt;<ref_value>&gt;访问器 [%autowidth, cols=8] |=== |种类 |表示形式 |置入 |种类测试 |指针访问 |`result`访问 |受检访问 |非受检访问</ref_value>

|<<ref_kind,`kind::array`>>
|<<ref_array>>
|<<ref_value_emplace_array>>
|<<ref_value_is_array>>
|<<ref_value_if_array>>
|<<ref_value_try_as_array>>
|<<ref_value_as_array>>
|<<ref_value_get_array>>

|<<ref_kind,`kind::object`>>
|<<ref_object>>
|<<ref_value_emplace_object>>
|<<ref_value_is_object>>
|<<ref_value_if_object>>
|<<ref_value_try_as_object>>
|<<ref_value_as_object>>
|<<ref_value_get_object>>

|<<ref_kind,`kind::string`>>
|<<ref_string>>
|<<ref_value_emplace_string>>
|<<ref_value_is_string>>
|<<ref_value_if_string>>
|<<ref_value_try_as_string>>
|<<ref_value_as_string>>
|<<ref_value_get_string>>

|<<ref_kind,`kind::int64`>>
|https://en.cppreference.com/w/cpp/types/integer[`std::int64_t`]
|<<ref_value_emplace_int64>>
|<<ref_value_is_int64>>
|<<ref_value_if_int64>>
|<<ref_value_try_as_int64>>
|<<ref_value_as_int64>>
|<<ref_value_get_int64>>

|<<ref_kind,`kind::uint64`>>
|https://en.cppreference.com/w/cpp/types/integer[`std::uint64_t`]
|<<ref_value_emplace_uint64>>
|<<ref_value_is_uint64>>
|<<ref_value_if_uint64>>
|<<ref_value_try_as_uint64>>
|<<ref_value_as_uint64>>
|<<ref_value_get_uint64>>

|<<ref_kind,`kind::double_`>>
|https://en.cppreference.com/w/cpp/language/types[`double`]
|<<ref_value_emplace_double>>
|<<ref_value_is_double>>
|<<ref_value_if_double>>
|<<ref_value_try_as_double>>
|<<ref_value_as_double>>
|<<ref_value_get_double>>

|<<ref_kind,`kind::bool_`>>
|https://en.cppreference.com/w/cpp/language/types[`bool`]
|<<ref_value_emplace_bool>>
|<<ref_value_is_bool>>
|<<ref_value_if_bool>>
|<<ref_value_try_as_bool>>
|<<ref_value_as_bool>>
|<<ref_value_get_bool>>

|<<ref_kind,`kind::null`>>
|https://en.cppreference.com/w/cpp/language/nullptr[`std::nullptr_t`]
|<<ref_value_emplace_null>>
|<<ref_value_is_null>>
^|— |&lt;<ref_value_try_as_null>&gt; ^|— ^|—</ref_value_try_as_null>

|===

&lt;<ref_value>&gt; 的置入成员函数返回对底层表示形式的类型化引用。例如，前例中对 &lt;<ref_value_emplace_string,`value::emplace_string`>&gt; 的调用返回一个 &lt;<ref_string,`string&`>&gt; 。下表列出了每种 kind 对应的底层类型：</ref_string,`string&`></ref_value_emplace_string,`value::emplace_string`></ref_value>

|===
|Kind|Type|Description

| <<ref_kind,`kind::object`>>
| <<ref_object>>
| An associative array of string keys mapping to <<ref_value>> elements with an
类似于 {std_unordered_map}，并保留插入顺序

| <<ref_kind,`kind::array`>>
| <<ref_array>>
| An ordered list of <<ref_value>> elements with an interface similar to
{std_vector}。

| <<ref_kind,`kind::string`>>
| <<ref_string>>
| A https://en.wikipedia.org/wiki/UTF-8[__UTF-8__] encoded
https://en.wikipedia.org/wiki/Unicode[Unicode]字符https://en.wikipedia.org/wiki/String_(computer_science)[字符串]，其接口类似于{std_string}。

| <<ref_kind,`kind::int64`>>
| `std::int64_t`
| A 64 bit signed integer.

| <<ref_kind,`kind::uint64`>>
| `std::uint64_t`
| A 64 bit unsigned integer.

| <<ref_kind,`kind::double_`>>
| `double`
| A `double` holding a floating-point value.

| <<ref_kind,`kind::bool_`>>
| https://en.cppreference.com/w/cpp/keyword/bool[`bool`]
| A `bool` holding `true` or `false`.

| <<ref_kind,`kind::null`>>
^| — | 一个表示空值的monostate值。 |===

置入操作的返回值可用于执行赋值，或捕获对底层元素的引用以供后续检查或修改：

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_5,indent=0]
----

如果已知 &lt;<ref_value>&gt; 的 &lt;<ref_kind>&gt;，可使用诸如 &lt;<ref_value_as_bool,`value::as_bool`>&gt; 或 &lt;<ref_value_as_string,`value::as_string`>&gt; 等函数，在不改变现有值的情况下获取对底层表示的引用：</ref_value_as_string,`value::as_string`></ref_value_as_bool,`value::as_bool`></ref_kind></ref_value>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_6,indent=0]
----

然而，如上所示，如果 &lt;<ref_value>&gt; 中的实际类型与函数签名所指定的类型不匹配，这些函数会抛出异常。这一行为可作为一种简洁的验证形式：以预期类型直接访问值，若 JSON 结构无效，则通过捕获异常进行处理。</ref_value>

我们可以通过请求一个可能为空的指针（而非引用）来查询值中特定种类的底层表示形式，而不会抛出异常。这里我们使用 &lt;<ref_value_if_string,`value::if_string`>&gt; 来条件执行赋值操作，而无需使用异常：</ref_value_if_string,`value::if_string`>

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_7,indent=0]
----

[TIP]
====
If the value's kind is known statically, a reference to the underlying
representation may be obtained by dereferencing the pointer without checking.
This avoids the code overhead of the possible exception when using, for example
<<ref_value_as_string,`value::as_string`>>:

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_8,indent=0]
----
====

返回 {ref_result} 的函数允许您同时使用上述两种方式：

[source]
----
include::../../../test/snippets.cpp[tag=snippet_value_9,indent=0]
----

=== 格式化输出
当将 &lt;<ref_value>&gt; 输出到 {std_ostream} 时，其结果等同于调用 &lt;<ref_serialize>&gt; 所生成的序列化 JSON。</ref_serialize></ref_value>
