userver
C++ Async Framework
Toggle main menu visibility
Loading...
Searching...
No Matches
value_builder.hpp
Go to the documentation of this file.
1
#
pragma
once
2
3
/// @file userver/formats/json/value_builder.hpp
4
/// @brief @copybrief formats::json::ValueBuilder
5
6
#
include
<
chrono
>
7
#
include
<
string_view
>
8
#
include
<
type_traits
>
9
10
#
include
<
userver
/
compiler
/
impl
/
nodebug
.
hpp
>
11
#
include
<
userver
/
formats
/
common
/
meta
.
hpp
>
12
#
include
<
userver
/
formats
/
common
/
transfer_tag
.
hpp
>
13
#
include
<
userver
/
formats
/
json
/
impl
/
mutable_value_wrapper
.
hpp
>
14
#
include
<
userver
/
formats
/
json
/
value
.
hpp
>
15
#
include
<
userver
/
utils
/
strong_typedef
.
hpp
>
16
17
USERVER_NAMESPACE_BEGIN
18
19
namespace
formats::
json
{
20
21
/// @ingroup userver_universal userver_containers userver_formats
22
///
23
/// @brief Builder for JSON.
24
///
25
/// Class provides methods for building JSON. For read only access to the
26
/// existing JSON values use formats::json::Value.
27
///
28
/// ## Example usage:
29
///
30
/// @snippet formats/json/value_builder_test.cpp Sample formats::json::ValueBuilder usage
31
///
32
/// ## Customization example:
33
///
34
/// @snippet formats/json/value_builder_test.cpp Sample Customization formats::json::ValueBuilder usage
35
///
36
/// @see @ref scripts/docs/en/userver/formats.md
37
class
ValueBuilder
final
{
38
public
:
39
struct
IterTraits
{
40
using
ValueType = formats::
json
::ValueBuilder;
41
using
Reference = formats::
json
::ValueBuilder&;
42
using
Pointer = formats::
json
::ValueBuilder*;
43
using
ContainerType = impl::MutableValueWrapper;
44
};
45
46
using
iterator = Iterator<
IterTraits
>;
47
48
/// Constructs a ValueBuilder that holds kNull
49
ValueBuilder
() =
default
;
50
51
/// Constructs a valueBuilder that holds default value for provided `type`.
52
ValueBuilder
(formats::common::
Type
type);
53
54
/// @brief Transfers the `ValueBuilder` object
55
/// @see formats::common::TransferTag for the transfer semantics
56
ValueBuilder
(common::TransferTag, ValueBuilder&&)
noexcept
;
57
58
ValueBuilder(
const
ValueBuilder& other);
59
// NOLINTNEXTLINE(performance-noexcept-move-constructor)
60
ValueBuilder(ValueBuilder&& other);
61
ValueBuilder& operator=(
const
ValueBuilder& other);
62
// NOLINTNEXTLINE(performance-noexcept-move-constructor)
63
ValueBuilder& operator=(ValueBuilder&& other);
64
65
ValueBuilder(
const
formats::
json
::
Value
& other);
66
ValueBuilder(formats::
json
::
Value
&& other);
67
68
/// @name Concrete type constructors
69
/// @{
70
ValueBuilder(std::nullptr_t)
71
: ValueBuilder
(
)
72
{}
73
ValueBuilder(
bool
t);
74
ValueBuilder(
const
char
* str);
75
ValueBuilder(
char
* str);
76
ValueBuilder(
const
std::string& str);
77
ValueBuilder(std::string_view str);
78
ValueBuilder(
int
t);
79
ValueBuilder(
unsigned
int
t);
80
ValueBuilder(uint64_t t);
81
ValueBuilder(int64_t t);
82
ValueBuilder(
float
t);
83
ValueBuilder(
double
t);
84
/// @}
85
86
/// Universal constructor using Serialize
87
template
<
typename
T>
88
ValueBuilder
(
const
T& t)
89
: ValueBuilder(DoSerialize(t))
90
{}
91
92
/// @brief Access member by key for modification.
93
/// @throw `TypeMismatchException` if not object or null value.
94
ValueBuilder
operator
[](std::string key);
95
/// @brief Access array member by index for modification.
96
/// @throw `TypeMismatchException` if not an array value.
97
/// @throw `OutOfBoundsException` if index is greater than size.
98
ValueBuilder
operator
[](std::size_t index);
99
/// @brief Access member by key for modification.
100
/// @throw `TypeMismatchException` if not object or null value.
101
template
<
typename
Tag,
utils
::StrongTypedefOps Ops>
102
requires
(
utils
::IsStrongTypedefLoggable(Ops))
103
ValueBuilder
operator
[](
utils
::StrongTypedef<Tag, std::string, Ops> key) {
104
return
(*
this
)[std::move(key.GetUnderlying())];
105
}
106
107
/// @brief Emplaces new member w/o a check whether the key already exists.
108
/// @warning May create invalid JSON with duplicate key.
109
/// @throw `TypeMismatchException` if not object or null value.
110
void
EmplaceNocheck
(std::string_view key, ValueBuilder value);
111
112
/// @brief Remove key from object. If key is missing nothing happens.
113
/// @throw `TypeMismatchException` if value is not an object.
114
void
Remove
(std::string_view key);
115
116
iterator begin();
117
iterator end();
118
119
/// @brief Returns whether the array or object is empty.
120
/// @throw `TypeMismatchException` if not an array or an object.
121
bool
IsEmpty
()
const
;
122
123
/// @brief Returns true if *this holds a Null (Type::kNull).
124
bool
IsNull
()
const
noexcept
;
125
126
/// @brief Returns true if *this is convertible to bool.
127
bool
IsBool
()
const
noexcept
;
128
129
/// @brief Returns true if *this is convertible to int.
130
bool
IsInt
()
const
noexcept
;
131
132
/// @brief Returns true if *this is convertible to int64_t.
133
bool
IsInt64
()
const
noexcept
;
134
135
/// @brief Returns true if *this is convertible to uint64_t.
136
bool
IsUInt64
()
const
noexcept
;
137
138
/// @brief Returns true if *this is convertible to double.
139
bool
IsDouble
()
const
noexcept
;
140
141
/// @brief Returns true if *this is convertible to std::string.
142
bool
IsString
()
const
noexcept
;
143
144
/// @brief Returns true if *this is an array (Type::kArray).
145
bool
IsArray
()
const
noexcept
;
146
147
/// @brief Returns true if *this holds a map (Type::kObject).
148
bool
IsObject
()
const
noexcept
;
149
150
/// @brief Returns array size or object members count.
151
/// @throw `TypeMismatchException` if not an array or an object.
152
std::size_t
GetSize
()
const
;
153
154
/// @brief Returns true if value holds a `key`.
155
/// @throw `TypeMismatchException` if `*this` is not a map or null.
156
bool
HasMember
(std::string_view key)
const
;
157
158
/// @brief Returns full path to this value.
159
std::string
GetPath
()
const
;
160
161
/// @brief Resize the array value or convert null value
162
/// into an array of requested size.
163
/// @throw `TypeMismatchException` if not an array or null.
164
void
Resize
(std::size_t size);
165
166
/// @brief Add element into the last position of array.
167
/// @throw `TypeMismatchException` if not an array or null.
168
void
PushBack
(ValueBuilder&& bld);
169
170
/// @brief Take out the resulting `Value` object.
171
/// After calling this method the object is in unspecified
172
/// (but valid - possibly null) state.
173
/// @throw `json::Exception` if called not from the root builder.
174
formats::
json
::
Value
ExtractValue
();
175
176
private
:
177
class
EmplaceEnabler {};
178
179
public
:
180
/// @cond
181
ValueBuilder(EmplaceEnabler, impl::MutableValueWrapper)
noexcept
;
182
/// @endcond
183
184
private
:
185
enum
class
CheckMemberExists { kYes, kNo };
186
187
explicit
ValueBuilder(impl::MutableValueWrapper)
noexcept
;
188
189
static
void
Copy(impl::Value& to,
const
ValueBuilder& from);
190
static
void
Move(impl::Value& to, ValueBuilder&& from);
191
192
impl::Value& AddMember(std::string_view key, CheckMemberExists);
193
194
template
<
typename
T>
195
USERVER_IMPL_NODEBUG_INLINE_FUNC
static
Value
DoSerialize(
const
T& t) {
196
static_assert
(
197
formats::common::impl::HasSerialize<
Value
, T>,
198
"There is no `Serialize(const T&, formats::serialize::To<json::Value>)` "
199
"in namespace of `T` or `formats::serialize`. "
200
""
201
"Probably you forgot to include the <userver/formats/serialize/common_containers.hpp> header "
202
"or one of the <formats/json/serialize_*.hpp> headers or you have not provided a `Serialize` function "
203
"overload."
204
);
205
206
return
Serialize(t, formats::
serialize
::
To
<
Value
>());
207
}
208
209
impl::MutableValueWrapper value_;
210
211
friend
class
Iterator<
IterTraits
, common::
IteratorDirection
::kForward>;
212
friend
class
Iterator<
IterTraits
, common::
IteratorDirection
::kReverse>;
213
};
214
215
template
<
typename
T>
216
requires
(std::is_integral<T>::value &&
sizeof
(T) <=
sizeof
(int64_t))
217
Value
Serialize(T value, formats::
serialize
::
To
<
Value
>) {
218
using
Type = std::conditional_t<std::is_signed<T>::value, int64_t, uint64_t>;
219
return
json
::ValueBuilder(
static_cast
<Type>(value))
.
ExtractValue
(
)
;
220
}
221
222
json
::
Value
Serialize(std::chrono::system_clock::time_point tp, formats::
serialize
::
To
<
Value
>);
223
224
/// Optimized maps of StrongTypedefs serialization for JSON
225
template
<
typename
T>
226
requires
(meta::
IsUniqueMap
<T> &&
utils
::IsStrongTypedefLoggable(T::key_type::kOps))
227
Value
Serialize
(
const
T& value, formats::
serialize
::
To
<
Value
>) {
228
json
::ValueBuilder builder
(
formats
::
common
::
Type
::
kObject
)
;
229
for
(
const
auto
& [key, value] : value) {
230
builder
.
EmplaceNocheck
(
key.GetUnderlying()
,
value
)
;
231
}
232
return
builder
.
ExtractValue
(
)
;
233
}
234
235
/// Optimized maps serialization for JSON
236
template
<
typename
T>
237
requires
meta::
IsUniqueMap
<T> && std::is_convertible_v<
typename
T::key_type, std::string>
238
Value
Serialize
(
const
T& value, formats::
serialize
::
To
<
Value
>) {
239
json
::ValueBuilder builder
(
formats
::
common
::
Type
::
kObject
)
;
240
for
(
const
auto
& [key, value] : value) {
241
builder
.
EmplaceNocheck
(
key
,
value
)
;
242
}
243
return
builder
.
ExtractValue
(
)
;
244
}
245
246
}
// namespace formats::json
247
248
USERVER_NAMESPACE_END
userver
formats
json
value_builder.hpp
Generated on
for userver by
Doxygen
1.17.0