RflySimSDK v4.10
RflySimSDK说明文档
载入中...
搜索中...
未找到
json.hpp
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013-2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34#include <nlohmann/adl_serializer.hpp>
35#include <nlohmann/byte_container_with_subtype.hpp>
36#include <nlohmann/detail/conversions/from_json.hpp>
37#include <nlohmann/detail/conversions/to_json.hpp>
38#include <nlohmann/detail/exceptions.hpp>
39#include <nlohmann/detail/hash.hpp>
40#include <nlohmann/detail/input/binary_reader.hpp>
41#include <nlohmann/detail/input/input_adapters.hpp>
42#include <nlohmann/detail/input/lexer.hpp>
43#include <nlohmann/detail/input/parser.hpp>
44#include <nlohmann/detail/iterators/internal_iterator.hpp>
45#include <nlohmann/detail/iterators/iter_impl.hpp>
46#include <nlohmann/detail/iterators/iteration_proxy.hpp>
47#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
48#include <nlohmann/detail/iterators/primitive_iterator.hpp>
49#include <nlohmann/detail/json_custom_base_class.hpp>
50#include <nlohmann/detail/json_pointer.hpp>
51#include <nlohmann/detail/json_ref.hpp>
52#include <nlohmann/detail/macro_scope.hpp>
53#include <nlohmann/detail/string_concat.hpp>
54#include <nlohmann/detail/string_escape.hpp>
55#include <nlohmann/detail/string_utils.hpp>
56#include <nlohmann/detail/meta/cpp_future.hpp>
57#include <nlohmann/detail/meta/type_traits.hpp>
58#include <nlohmann/detail/output/binary_writer.hpp>
59#include <nlohmann/detail/output/output_adapters.hpp>
60#include <nlohmann/detail/output/serializer.hpp>
61#include <nlohmann/detail/value_t.hpp>
62#include <nlohmann/json_fwd.hpp>
63#include <nlohmann/ordered_map.hpp>
64
65#if defined(JSON_HAS_CPP_17)
66 #if JSON_HAS_STATIC_RTTI
67 #include <any>
68 #endif
69 #include <string_view>
70#endif
71
72/*!
73@brief namespace for Niels Lohmann
74@see https://github.com/nlohmann
75@since version 1.0.0
76*/
77NLOHMANN_JSON_NAMESPACE_BEGIN
78
79/*!
80@brief a class to store JSON values
81
82@internal
83@invariant The member variables @a m_value and @a m_type have the following
84relationship:
85- If `m_type == value_t::object`, then `m_value.object != nullptr`.
86- If `m_type == value_t::array`, then `m_value.array != nullptr`.
87- If `m_type == value_t::string`, then `m_value.string != nullptr`.
88The invariants are checked by member function assert_invariant().
89
90@note ObjectType trick from https://stackoverflow.com/a/9860911
91@endinternal
92
93@since version 1.0.0
94
95@nosubgrouping
96*/
97NLOHMANN_BASIC_JSON_TPL_DECLARATION
98class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
99 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
100{
101 private:
102 template<detail::value_t> friend struct detail::external_constructor;
103
104 template<typename>
105 friend class ::nlohmann::json_pointer;
106 // can be restored when json_pointer backwards compatibility is removed
107 // friend ::nlohmann::json_pointer<StringType>;
108
109 template<typename BasicJsonType, typename InputType>
110 friend class ::nlohmann::detail::parser;
111 friend ::nlohmann::detail::serializer<basic_json>;
112 template<typename BasicJsonType>
113 friend class ::nlohmann::detail::iter_impl;
114 template<typename BasicJsonType, typename CharType>
115 friend class ::nlohmann::detail::binary_writer;
116 template<typename BasicJsonType, typename InputType, typename SAX>
117 friend class ::nlohmann::detail::binary_reader;
118 template<typename BasicJsonType, typename InputAdapterType>
119 friend class ::nlohmann::detail::json_sax_dom_parser;
120 template<typename BasicJsonType, typename InputAdapterType>
121 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
122 friend class ::nlohmann::detail::exception;
123
124 /// workaround type for MSVC
125 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
126 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
127
128 JSON_PRIVATE_UNLESS_TESTED:
129 // convenience aliases for types residing in namespace detail;
130 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
131
132 template<typename InputAdapterType>
133 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
134 InputAdapterType adapter,
135 detail::parser_callback_t<basic_json>cb = nullptr,
136 const bool allow_exceptions = true,
137 const bool ignore_comments = false,
138 const bool ignore_trailing_commas = false
139 )
140 {
141 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
142 std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas);
143 }
144
145 private:
146 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
147 template<typename BasicJsonType>
148 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
149 template<typename BasicJsonType>
150 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
151 template<typename Iterator>
152 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
153 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
154
155 template<typename CharType>
156 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
157
158 template<typename InputType>
159 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
160 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
161
162 JSON_PRIVATE_UNLESS_TESTED:
163 using serializer = ::nlohmann::detail::serializer<basic_json>;
164
165 public:
166 using value_t = detail::value_t;
167 /// JSON Pointer, see @ref nlohmann::json_pointer
168 using json_pointer = ::nlohmann::json_pointer<StringType>;
169 template<typename T, typename SFINAE>
170 using json_serializer = JSONSerializer<T, SFINAE>;
171 /// how to treat decoding errors
173 /// how to treat CBOR tags
175 /// how to encode BJData
177 /// helper type for initializer lists of basic_json values
178 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
179
180 using input_format_t = detail::input_format_t;
181 /// SAX interface type, see @ref nlohmann::json_sax
183
184 ////////////////
185 // exceptions //
186 ////////////////
187
188 /// @name exceptions
189 /// Classes to implement user-defined exceptions.
190 /// @{
191
192 using exception = detail::exception;
193 using parse_error = detail::parse_error;
194 using invalid_iterator = detail::invalid_iterator;
195 using type_error = detail::type_error;
196 using out_of_range = detail::out_of_range;
197 using other_error = detail::other_error;
198
199 /// @}
200
201 /////////////////////
202 // container types //
203 /////////////////////
204
205 /// @name container types
206 /// The canonic container types to use @ref basic_json like any other STL
207 /// container.
208 /// @{
209
210 /// the type of elements in a basic_json container
212
213 /// the type of an element reference
215 /// the type of an element const reference
217
218 /// a type to represent differences between iterators
219 using difference_type = std::ptrdiff_t;
220 /// a type to represent container sizes
221 using size_type = std::size_t;
222
223 /// the allocator type
224 using allocator_type = AllocatorType<basic_json>;
225
226 /// the type of an element pointer
227 using pointer = typename std::allocator_traits<allocator_type>::pointer;
228 /// the type of an element const pointer
229 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
230
231 /// an iterator for a basic_json container
232 using iterator = iter_impl<basic_json>;
233 /// a const iterator for a basic_json container
234 using const_iterator = iter_impl<const basic_json>;
235 /// a reverse iterator for a basic_json container
236 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
237 /// a const reverse iterator for a basic_json container
238 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
239
240 /// @}
241
242 /// @brief returns the allocator associated with the container
243 /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
245 {
246 return allocator_type();
247 }
248
249 /// @brief returns version information on the library
250 /// @sa https://json.nlohmann.me/api/basic_json/meta/
251 JSON_HEDLEY_WARN_UNUSED_RESULT
253 {
254 basic_json result;
255
256 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
257 result["name"] = "JSON for Modern C++";
258 result["url"] = "https://github.com/nlohmann/json";
259 result["version"]["string"] =
260 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
261 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
262 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
263 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
264 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
265 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
266
267#ifdef _WIN32
268 result["platform"] = "win32";
269#elif defined __linux__
270 result["platform"] = "linux";
271#elif defined __APPLE__
272 result["platform"] = "apple";
273#elif defined __unix__
274 result["platform"] = "unix";
275#else
276 result["platform"] = "unknown";
277#endif
278
279#if defined(__ICC) || defined(__INTEL_COMPILER)
280 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
281#elif defined(__clang__)
282 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
283#elif defined(__GNUC__) || defined(__GNUG__)
284 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
285 std::to_string(__GNUC__), '.',
286 std::to_string(__GNUC_MINOR__), '.',
287 std::to_string(__GNUC_PATCHLEVEL__))
288 }
289 };
290#elif defined(__HP_cc) || defined(__HP_aCC)
291 result["compiler"] = "hp"
292#elif defined(__IBMCPP__)
293 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
294#elif defined(_MSC_VER)
295 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
296#elif defined(__PGI)
297 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
298#elif defined(__SUNPRO_CC)
299 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
300#else
301 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
302#endif
303
304#if defined(_MSVC_LANG)
305 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
306#elif defined(__cplusplus)
307 result["compiler"]["c++"] = std::to_string(__cplusplus);
308#else
309 result["compiler"]["c++"] = "unknown";
310#endif
311 return result;
312 }
313
314 ///////////////////////////
315 // JSON value data types //
316 ///////////////////////////
317
318 /// @name JSON value data types
319 /// The data types to store a JSON value. These types are derived from
320 /// the template arguments passed to class @ref basic_json.
321 /// @{
322
323 /// @brief default object key comparator type
324 /// The actual object key comparator type (@ref object_comparator_t) may be
325 /// different.
326 /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
327#if defined(JSON_HAS_CPP_14)
328 // use of transparent comparator avoids unnecessary repeated construction of temporaries
329 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
330 using default_object_comparator_t = std::less<>;
331#else
332 using default_object_comparator_t = std::less<StringType>;
333#endif
334
335 /// @brief a type for an object
336 /// @sa https://json.nlohmann.me/api/basic_json/object_t/
337 using object_t = ObjectType<StringType,
340 AllocatorType<std::pair<const StringType,
341 basic_json>>>;
342
343 /// @brief a type for an array
344 /// @sa https://json.nlohmann.me/api/basic_json/array_t/
345 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
346
347 /// @brief a type for a string
348 /// @sa https://json.nlohmann.me/api/basic_json/string_t/
349 using string_t = StringType;
350
351 /// @brief a type for a boolean
352 /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
353 using boolean_t = BooleanType;
354
355 /// @brief a type for a number (integer)
356 /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
357 using number_integer_t = NumberIntegerType;
358
359 /// @brief a type for a number (unsigned)
360 /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
361 using number_unsigned_t = NumberUnsignedType;
362
363 /// @brief a type for a number (floating-point)
364 /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
365 using number_float_t = NumberFloatType;
366
367 /// @brief a type for a packed binary type
368 /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
369 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
370
371 /// @brief object key comparator type
372 /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
373 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
374
375 /// @}
376
377 private:
378
379 /// helper for exception-safe object creation
380 template<typename T, typename... Args>
381 JSON_HEDLEY_RETURNS_NON_NULL
382 static T* create(Args&& ... args)
383 {
384 AllocatorType<T> alloc;
385 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
386
387 auto deleter = [&](T * obj)
388 {
389 AllocatorTraits::deallocate(alloc, obj, 1);
390 };
391 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
392 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
393 JSON_ASSERT(obj != nullptr);
394 return obj.release();
395 }
396
397 ////////////////////////
398 // JSON value storage //
399 ////////////////////////
400
401 JSON_PRIVATE_UNLESS_TESTED:
402 /*!
403 @brief a JSON value
404
405 The actual storage for a JSON value of the @ref basic_json class. This
406 union combines the different storage types for the JSON value types
407 defined in @ref value_t.
408
409 JSON type | value_t type | used type
410 --------- | --------------- | ------------------------
411 object | object | pointer to @ref object_t
412 array | array | pointer to @ref array_t
413 string | string | pointer to @ref string_t
414 boolean | boolean | @ref boolean_t
415 number | number_integer | @ref number_integer_t
416 number | number_unsigned | @ref number_unsigned_t
417 number | number_float | @ref number_float_t
418 binary | binary | pointer to @ref binary_t
419 null | null | *no value is stored*
420
421 @note Variable-length types (objects, arrays, and strings) are stored as
422 pointers. The size of the union should not exceed 64 bits if the default
423 value types are used.
424
425 @since version 1.0.0
426 */
427 union json_value
428 {
429 /// object (stored with pointer to save storage)
430 object_t* object;
431 /// array (stored with pointer to save storage)
432 array_t* array;
433 /// string (stored with pointer to save storage)
434 string_t* string;
435 /// binary (stored with pointer to save storage)
436 binary_t* binary;
437 /// boolean
438 boolean_t boolean;
439 /// number (integer)
440 number_integer_t number_integer;
441 /// number (unsigned integer)
442 number_unsigned_t number_unsigned;
443 /// number (floating-point)
444 number_float_t number_float;
445
446 /// default constructor (for null values)
447 json_value() = default;
448 /// constructor for booleans
449 json_value(boolean_t v) noexcept : boolean(v) {}
450 /// constructor for numbers (integer)
451 json_value(number_integer_t v) noexcept : number_integer(v) {}
452 /// constructor for numbers (unsigned)
453 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
454 /// constructor for numbers (floating-point)
455 json_value(number_float_t v) noexcept : number_float(v) {}
456 /// constructor for empty values of a given type
457 json_value(value_t t)
458 {
459 switch (t)
460 {
461 case value_t::object:
462 {
463 object = create<object_t>();
464 break;
465 }
466
467 case value_t::array:
468 {
469 array = create<array_t>();
470 break;
471 }
472
473 case value_t::string:
474 {
475 string = create<string_t>("");
476 break;
477 }
478
479 case value_t::binary:
480 {
481 binary = create<binary_t>();
482 break;
483 }
484
485 case value_t::boolean:
486 {
487 boolean = static_cast<boolean_t>(false);
488 break;
489 }
490
491 case value_t::number_integer:
492 {
493 number_integer = static_cast<number_integer_t>(0);
494 break;
495 }
496
497 case value_t::number_unsigned:
498 {
499 number_unsigned = static_cast<number_unsigned_t>(0);
500 break;
501 }
502
503 case value_t::number_float:
504 {
505 number_float = static_cast<number_float_t>(0.0);
506 break;
507 }
508
509 case value_t::null:
510 {
511 object = nullptr; // silence warning, see #821
512 break;
513 }
514
515 case value_t::discarded:
516 default:
517 {
518 object = nullptr; // silence warning, see #821
519 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
520 {
521 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
522 }
523 break;
524 }
525 }
526 }
527
528 /// constructor for strings
529 json_value(const string_t& value) : string(create<string_t>(value)) {}
530
531 /// constructor for rvalue strings
532 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
533
534 /// constructor for objects
535 json_value(const object_t& value) : object(create<object_t>(value)) {}
536
537 /// constructor for rvalue objects
538 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
539
540 /// constructor for arrays
541 json_value(const array_t& value) : array(create<array_t>(value)) {}
542
543 /// constructor for rvalue arrays
544 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
545
546 /// constructor for binary arrays
547 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
548
549 /// constructor for rvalue binary arrays
550 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
551
552 /// constructor for binary arrays (internal type)
553 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
554
555 /// constructor for rvalue binary arrays (internal type)
556 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
557
558 void destroy(value_t t)
559 {
560 if (
561 (t == value_t::object && object == nullptr) ||
562 (t == value_t::array && array == nullptr) ||
563 (t == value_t::string && string == nullptr) ||
564 (t == value_t::binary && binary == nullptr)
565 )
566 {
567 // not initialized (e.g., due to exception in the ctor)
568 return;
569 }
570 if (t == value_t::array || t == value_t::object)
571 {
572 // flatten the current json_value to a heap-allocated stack
573 std::vector<basic_json> stack;
574
575 // move the top-level items to stack
576 if (t == value_t::array)
577 {
578 stack.reserve(array->size());
579 std::move(array->begin(), array->end(), std::back_inserter(stack));
580 }
581 else
582 {
583 stack.reserve(object->size());
584 for (auto&& it : *object)
585 {
586 stack.push_back(std::move(it.second));
587 }
588 }
589
590 while (!stack.empty())
591 {
592 // move the last item to a local variable to be processed
593 basic_json current_item(std::move(stack.back()));
594 stack.pop_back();
595
596 // if current_item is array/object, move
597 // its children to the stack to be processed later
598 if (current_item.is_array())
599 {
600 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
601
602 current_item.m_data.m_value.array->clear();
603 }
604 else if (current_item.is_object())
605 {
606 for (auto&& it : *current_item.m_data.m_value.object)
607 {
608 stack.push_back(std::move(it.second));
609 }
610
611 current_item.m_data.m_value.object->clear();
612 }
613
614 // it's now safe that current_item gets destructed
615 // since it doesn't have any children
616 }
617 }
618
619 switch (t)
620 {
621 case value_t::object:
622 {
623 AllocatorType<object_t> alloc;
624 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
625 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
626 break;
627 }
628
629 case value_t::array:
630 {
631 AllocatorType<array_t> alloc;
632 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
633 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
634 break;
635 }
636
637 case value_t::string:
638 {
639 AllocatorType<string_t> alloc;
640 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
641 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
642 break;
643 }
644
645 case value_t::binary:
646 {
647 AllocatorType<binary_t> alloc;
648 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
649 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
650 break;
651 }
652
653 case value_t::null:
654 case value_t::boolean:
655 case value_t::number_integer:
656 case value_t::number_unsigned:
657 case value_t::number_float:
658 case value_t::discarded:
659 default:
660 {
661 break;
662 }
663 }
664 }
665 };
666
667 private:
668 /*!
669 @brief checks the class invariants
670
671 This function asserts the class invariants. It needs to be called at the
672 end of every constructor to make sure that created objects respect the
673 invariant. Furthermore, it has to be called each time the type of a JSON
674 value is changed, because the invariant expresses a relationship between
675 @a m_type and @a m_value.
676
677 Furthermore, the parent relation is checked for arrays and objects: If
678 @a check_parents true and the value is an array or object, then the
679 container's elements must have the current value as parent.
680
681 @param[in] check_parents whether the parent relation should be checked.
682 The value is true by default and should only be set to false
683 during destruction of objects when the invariant does not
684 need to hold.
685 */
686 void assert_invariant(bool check_parents = true) const noexcept
687 {
688 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
689 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
690 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
691 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
692
693#if JSON_DIAGNOSTICS
694 JSON_TRY
695 {
696 // cppcheck-suppress assertWithSideEffect
697 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
698 {
699 return j.m_parent == this;
700 }));
701 }
702 JSON_CATCH(...) {} // LCOV_EXCL_LINE
703#endif
704 static_cast<void>(check_parents);
705 }
706
707 void set_parents()
708 {
709#if JSON_DIAGNOSTICS
710 switch (m_data.m_type)
711 {
712 case value_t::array:
713 {
714 for (auto& element : *m_data.m_value.array)
715 {
716 element.m_parent = this;
717 }
718 break;
719 }
720
721 case value_t::object:
722 {
723 for (auto& element : *m_data.m_value.object)
724 {
725 element.second.m_parent = this;
726 }
727 break;
728 }
729
730 case value_t::null:
731 case value_t::string:
732 case value_t::boolean:
733 case value_t::number_integer:
734 case value_t::number_unsigned:
735 case value_t::number_float:
736 case value_t::binary:
737 case value_t::discarded:
738 default:
739 break;
740 }
741#endif
742 }
743
744 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
745 {
746#if JSON_DIAGNOSTICS
747 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
748 {
749 (it + i)->m_parent = this;
750 }
751#else
752 static_cast<void>(count_set_parents);
753#endif
754 return it;
755 }
756
757 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
758 {
759#if JSON_DIAGNOSTICS
760 if (old_capacity != detail::unknown_size())
761 {
762 // see https://github.com/nlohmann/json/issues/2838
763 JSON_ASSERT(type() == value_t::array);
764 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
765 {
766 // capacity has changed: update all parents
767 set_parents();
768 return j;
769 }
770 }
771
772 // ordered_json uses a vector internally, so pointers could have
773 // been invalidated; see https://github.com/nlohmann/json/issues/2962
774#ifdef JSON_HEDLEY_MSVC_VERSION
775#pragma warning(push )
776#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
777#endif
778 if (detail::is_ordered_map<object_t>::value)
779 {
780 set_parents();
781 return j;
782 }
783#ifdef JSON_HEDLEY_MSVC_VERSION
784#pragma warning( pop )
785#endif
786
787 j.m_parent = this;
788#else
789 static_cast<void>(j);
790 static_cast<void>(old_capacity);
791#endif
792 return j;
793 }
794
795 public:
796 //////////////////////////
797 // JSON parser callback //
798 //////////////////////////
799
800 /// @brief parser event types
801 /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
803
804 /// @brief per-element parser callback type
805 /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
806 using parser_callback_t = detail::parser_callback_t<basic_json>;
807
808 //////////////////
809 // constructors //
810 //////////////////
811
812 /// @name constructors and destructors
813 /// Constructors of class @ref basic_json, copy/move constructor, copy
814 /// assignment, static functions creating objects, and the destructor.
815 /// @{
816
817 /// @brief create an empty value with a given type
818 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
819 basic_json(const value_t v)
820 : m_data(v)
821 {
822 assert_invariant();
823 }
824
825 /// @brief create a null object
826 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
827 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
828 : basic_json(value_t::null)
829 {
830 assert_invariant();
831 }
832
833 /// @brief create a JSON value from compatible types
834 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
835 template < typename CompatibleType,
836 typename U = detail::uncvref_t<CompatibleType>,
837 detail::enable_if_t <
839 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
840 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
841 std::forward<CompatibleType>(val))))
842 {
843 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
844 set_parents();
845 assert_invariant();
846 }
847
848 /// @brief create a JSON value from an existing one
849 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
850 template < typename BasicJsonType,
851 detail::enable_if_t <
852 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
853 basic_json(const BasicJsonType& val)
854#if JSON_DIAGNOSTIC_POSITIONS
855 : start_position(val.start_pos()),
856 end_position(val.end_pos())
857#endif
858 {
859 using other_boolean_t = typename BasicJsonType::boolean_t;
860 using other_number_float_t = typename BasicJsonType::number_float_t;
861 using other_number_integer_t = typename BasicJsonType::number_integer_t;
862 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
863 using other_string_t = typename BasicJsonType::string_t;
864 using other_object_t = typename BasicJsonType::object_t;
865 using other_array_t = typename BasicJsonType::array_t;
866 using other_binary_t = typename BasicJsonType::binary_t;
867
868 switch (val.type())
869 {
870 case value_t::boolean:
871 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
872 break;
873 case value_t::number_float:
874 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
875 break;
876 case value_t::number_integer:
877 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
878 break;
879 case value_t::number_unsigned:
880 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
881 break;
882 case value_t::string:
883 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
884 break;
885 case value_t::object:
886 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
887 break;
888 case value_t::array:
889 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
890 break;
891 case value_t::binary:
892 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
893 break;
894 case value_t::null:
895 *this = nullptr;
896 break;
897 case value_t::discarded:
898 m_data.m_type = value_t::discarded;
899 break;
900 default: // LCOV_EXCL_LINE
901 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
902 }
903 JSON_ASSERT(m_data.m_type == val.type());
904
905 set_parents();
906 assert_invariant();
907 }
908
909 /// @brief create a container (array or object) from an initializer list
910 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
912 bool type_deduction = true,
913 value_t manual_type = value_t::array)
914 {
915 // check if each element is an array with two elements whose first
916 // element is a string
917 bool is_an_object = std::all_of(init.begin(), init.end(),
918 [](const detail::json_ref<basic_json>& element_ref)
919 {
920 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
921 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
922 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
923 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
924 });
925
926 // adjust type if type deduction is not wanted
927 if (!type_deduction)
928 {
929 // if an array is wanted, do not create an object though possible
930 if (manual_type == value_t::array)
931 {
932 is_an_object = false;
933 }
934
935 // if an object is wanted but impossible, throw an exception
936 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
937 {
938 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
939 }
940 }
941
942 if (is_an_object)
943 {
944 // the initializer list is a list of pairs -> create an object
945 m_data.m_type = value_t::object;
946 m_data.m_value = value_t::object;
947
948 for (auto& element_ref : init)
949 {
950 auto element = element_ref.moved_or_copied();
951 m_data.m_value.object->emplace(
952 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
953 std::move((*element.m_data.m_value.array)[1]));
954 }
955 }
956 else
957 {
958 // the initializer list describes an array -> create an array
959 m_data.m_type = value_t::array;
960 m_data.m_value.array = create<array_t>(init.begin(), init.end());
961 }
962
963 set_parents();
964 assert_invariant();
965 }
966
967 /// @brief explicitly create a binary array (without subtype)
968 /// @sa https://json.nlohmann.me/api/basic_json/binary/
969 JSON_HEDLEY_WARN_UNUSED_RESULT
970 static basic_json binary(const typename binary_t::container_type& init)
971 {
972 auto res = basic_json();
973 res.m_data.m_type = value_t::binary;
974 res.m_data.m_value = init;
975 return res;
976 }
977
978 /// @brief explicitly create a binary array (with subtype)
979 /// @sa https://json.nlohmann.me/api/basic_json/binary/
980 JSON_HEDLEY_WARN_UNUSED_RESULT
981 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
982 {
983 auto res = basic_json();
984 res.m_data.m_type = value_t::binary;
985 res.m_data.m_value = binary_t(init, subtype);
986 return res;
987 }
988
989 /// @brief explicitly create a binary array
990 /// @sa https://json.nlohmann.me/api/basic_json/binary/
991 JSON_HEDLEY_WARN_UNUSED_RESULT
992 static basic_json binary(typename binary_t::container_type&& init)
993 {
994 auto res = basic_json();
995 res.m_data.m_type = value_t::binary;
996 res.m_data.m_value = std::move(init);
997 return res;
998 }
999
1000 /// @brief explicitly create a binary array (with subtype)
1001 /// @sa https://json.nlohmann.me/api/basic_json/binary/
1002 JSON_HEDLEY_WARN_UNUSED_RESULT
1003 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
1004 {
1005 auto res = basic_json();
1006 res.m_data.m_type = value_t::binary;
1007 res.m_data.m_value = binary_t(std::move(init), subtype);
1008 return res;
1009 }
1010
1011 /// @brief explicitly create an array from an initializer list
1012 /// @sa https://json.nlohmann.me/api/basic_json/array/
1013 JSON_HEDLEY_WARN_UNUSED_RESULT
1015 {
1016 return basic_json(init, false, value_t::array);
1017 }
1018
1019 /// @brief explicitly create an object from an initializer list
1020 /// @sa https://json.nlohmann.me/api/basic_json/object/
1021 JSON_HEDLEY_WARN_UNUSED_RESULT
1023 {
1024 return basic_json(init, false, value_t::object);
1025 }
1026
1027 /// @brief construct an array with count copies of given value
1028 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1030 m_data{cnt, val}
1031 {
1032 set_parents();
1033 assert_invariant();
1034 }
1035
1036 /// @brief construct a JSON container given an iterator range
1037 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1038 template < class InputIT, typename std::enable_if <
1039 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
1040 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
1041 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
1042 {
1043 JSON_ASSERT(first.m_object != nullptr);
1044 JSON_ASSERT(last.m_object != nullptr);
1045
1046 // make sure the iterator fits the current value
1047 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1048 {
1049 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
1050 }
1051
1052 // copy type from the first iterator
1053 m_data.m_type = first.m_object->m_data.m_type;
1054
1055 // check if the iterator range is complete for primitive values
1056 switch (m_data.m_type)
1057 {
1058 case value_t::boolean:
1059 case value_t::number_float:
1060 case value_t::number_integer:
1061 case value_t::number_unsigned:
1062 case value_t::string:
1063 {
1064 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
1065 || !last.m_it.primitive_iterator.is_end()))
1066 {
1067 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
1068 }
1069 break;
1070 }
1071
1072 case value_t::null:
1073 case value_t::object:
1074 case value_t::array:
1075 case value_t::binary:
1076 case value_t::discarded:
1077 default:
1078 break;
1079 }
1080
1081 switch (m_data.m_type)
1082 {
1083 case value_t::number_integer:
1084 {
1085 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
1086 break;
1087 }
1088
1089 case value_t::number_unsigned:
1090 {
1091 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
1092 break;
1093 }
1094
1095 case value_t::number_float:
1096 {
1097 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
1098 break;
1099 }
1100
1101 case value_t::boolean:
1102 {
1103 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
1104 break;
1105 }
1106
1107 case value_t::string:
1108 {
1109 m_data.m_value = *first.m_object->m_data.m_value.string;
1110 break;
1111 }
1112
1113 case value_t::object:
1114 {
1115 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
1116 last.m_it.object_iterator);
1117 break;
1118 }
1119
1120 case value_t::array:
1121 {
1122 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
1123 last.m_it.array_iterator);
1124 break;
1125 }
1126
1127 case value_t::binary:
1128 {
1129 m_data.m_value = *first.m_object->m_data.m_value.binary;
1130 break;
1131 }
1132
1133 case value_t::null:
1134 case value_t::discarded:
1135 default:
1136 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
1137 }
1138
1139 set_parents();
1140 assert_invariant();
1141 }
1142
1143 ///////////////////////////////////////
1144 // other constructors and destructor //
1145 ///////////////////////////////////////
1146
1147 template<typename JsonRef,
1148 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
1149 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
1150 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
1151
1152 /// @brief copy constructor
1153 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1155 : json_base_class_t(other)
1156#if JSON_DIAGNOSTIC_POSITIONS
1157 , start_position(other.start_position)
1158 , end_position(other.end_position)
1159#endif
1160 {
1161 m_data.m_type = other.m_data.m_type;
1162 // check of passed value is valid
1163 other.assert_invariant();
1164
1165 switch (m_data.m_type)
1166 {
1167 case value_t::object:
1168 {
1169 m_data.m_value = *other.m_data.m_value.object;
1170 break;
1171 }
1172
1173 case value_t::array:
1174 {
1175 m_data.m_value = *other.m_data.m_value.array;
1176 break;
1177 }
1178
1179 case value_t::string:
1180 {
1181 m_data.m_value = *other.m_data.m_value.string;
1182 break;
1183 }
1184
1185 case value_t::boolean:
1186 {
1187 m_data.m_value = other.m_data.m_value.boolean;
1188 break;
1189 }
1190
1191 case value_t::number_integer:
1192 {
1193 m_data.m_value = other.m_data.m_value.number_integer;
1194 break;
1195 }
1196
1197 case value_t::number_unsigned:
1198 {
1199 m_data.m_value = other.m_data.m_value.number_unsigned;
1200 break;
1201 }
1202
1203 case value_t::number_float:
1204 {
1205 m_data.m_value = other.m_data.m_value.number_float;
1206 break;
1207 }
1208
1209 case value_t::binary:
1210 {
1211 m_data.m_value = *other.m_data.m_value.binary;
1212 break;
1213 }
1214
1215 case value_t::null:
1216 case value_t::discarded:
1217 default:
1218 break;
1219 }
1220
1221 set_parents();
1222 assert_invariant();
1223 }
1224
1225 /// @brief move constructor
1226 /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1227 basic_json(basic_json&& other) noexcept
1228 : json_base_class_t(std::forward<json_base_class_t>(other)),
1229 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
1230#if JSON_DIAGNOSTIC_POSITIONS
1231 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
1232 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
1233#endif
1234 {
1235 // check that the passed value is valid
1236 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
1237
1238 // invalidate payload
1239 other.m_data.m_type = value_t::null;
1240 other.m_data.m_value = {};
1241
1242#if JSON_DIAGNOSTIC_POSITIONS
1243 other.start_position = std::string::npos;
1244 other.end_position = std::string::npos;
1245#endif
1246
1247 set_parents();
1248 assert_invariant();
1249 }
1250
1251 /// @brief copy assignment
1252 /// @sa https://json.nlohmann.me/api/basic_json/operator=/
1253 basic_json& operator=(basic_json other) noexcept ( // NOLINT(cppcoreguidelines-c-copy-assignment-signature,misc-unconventional-assign-operator)
1254 std::is_nothrow_move_constructible<value_t>::value&&
1255 std::is_nothrow_move_assignable<value_t>::value&&
1256 std::is_nothrow_move_constructible<json_value>::value&&
1257 std::is_nothrow_move_assignable<json_value>::value&&
1258 std::is_nothrow_move_assignable<json_base_class_t>::value
1259 )
1260 {
1261 // check that the passed value is valid
1262 other.assert_invariant();
1263
1264 using std::swap;
1265 swap(m_data.m_type, other.m_data.m_type);
1266 swap(m_data.m_value, other.m_data.m_value);
1267
1268#if JSON_DIAGNOSTIC_POSITIONS
1269 swap(start_position, other.start_position);
1270 swap(end_position, other.end_position);
1271#endif
1272
1273 json_base_class_t::operator=(std::move(other));
1274
1275 set_parents();
1276 assert_invariant();
1277 return *this;
1278 }
1279
1280 /// @brief destructor
1281 /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
1282 ~basic_json() noexcept
1283 {
1284 assert_invariant(false);
1285 }
1286
1287 /// @}
1288
1289 public:
1290 ///////////////////////
1291 // object inspection //
1292 ///////////////////////
1293
1294 /// @name object inspection
1295 /// Functions to inspect the type of a JSON value.
1296 /// @{
1297
1298 /// @brief serialization
1299 /// @sa https://json.nlohmann.me/api/basic_json/dump/
1300 string_t dump(const int indent = -1,
1301 const char indent_char = ' ',
1302 const bool ensure_ascii = false,
1303 const error_handler_t error_handler = error_handler_t::strict) const
1304 {
1305 string_t result;
1306 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
1307
1308 if (indent >= 0)
1309 {
1310 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
1311 }
1312 else
1313 {
1314 s.dump(*this, false, ensure_ascii, 0);
1315 }
1316
1317 return result;
1318 }
1319
1320 /// @brief return the type of the JSON value (explicit)
1321 /// @sa https://json.nlohmann.me/api/basic_json/type/
1322 constexpr value_t type() const noexcept
1323 {
1324 return m_data.m_type;
1325 }
1326
1327 /// @brief return whether type is primitive
1328 /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
1329 constexpr bool is_primitive() const noexcept
1330 {
1331 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
1332 }
1333
1334 /// @brief return whether type is structured
1335 /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
1336 constexpr bool is_structured() const noexcept
1337 {
1338 return is_array() || is_object();
1339 }
1340
1341 /// @brief return whether value is null
1342 /// @sa https://json.nlohmann.me/api/basic_json/is_null/
1343 constexpr bool is_null() const noexcept
1344 {
1345 return m_data.m_type == value_t::null;
1346 }
1347
1348 /// @brief return whether value is a boolean
1349 /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
1350 constexpr bool is_boolean() const noexcept
1351 {
1352 return m_data.m_type == value_t::boolean;
1353 }
1354
1355 /// @brief return whether value is a number
1356 /// @sa https://json.nlohmann.me/api/basic_json/is_number/
1357 constexpr bool is_number() const noexcept
1358 {
1359 return is_number_integer() || is_number_float();
1360 }
1361
1362 /// @brief return whether value is an integer number
1363 /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
1364 constexpr bool is_number_integer() const noexcept
1365 {
1366 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
1367 }
1368
1369 /// @brief return whether value is an unsigned integer number
1370 /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
1371 constexpr bool is_number_unsigned() const noexcept
1372 {
1373 return m_data.m_type == value_t::number_unsigned;
1374 }
1375
1376 /// @brief return whether value is a floating-point number
1377 /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
1378 constexpr bool is_number_float() const noexcept
1379 {
1380 return m_data.m_type == value_t::number_float;
1381 }
1382
1383 /// @brief return whether value is an object
1384 /// @sa https://json.nlohmann.me/api/basic_json/is_object/
1385 constexpr bool is_object() const noexcept
1386 {
1387 return m_data.m_type == value_t::object;
1388 }
1389
1390 /// @brief return whether value is an array
1391 /// @sa https://json.nlohmann.me/api/basic_json/is_array/
1392 constexpr bool is_array() const noexcept
1393 {
1394 return m_data.m_type == value_t::array;
1395 }
1396
1397 /// @brief return whether value is a string
1398 /// @sa https://json.nlohmann.me/api/basic_json/is_string/
1399 constexpr bool is_string() const noexcept
1400 {
1401 return m_data.m_type == value_t::string;
1402 }
1403
1404 /// @brief return whether value is a binary array
1405 /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
1406 constexpr bool is_binary() const noexcept
1407 {
1408 return m_data.m_type == value_t::binary;
1409 }
1410
1411 /// @brief return whether value is discarded
1412 /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
1413 constexpr bool is_discarded() const noexcept
1414 {
1415 return m_data.m_type == value_t::discarded;
1416 }
1417
1418 /// @brief return the type of the JSON value (implicit)
1419 /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
1420 constexpr operator value_t() const noexcept
1421 {
1422 return m_data.m_type;
1423 }
1424
1425 /// @}
1426
1427 private:
1428 //////////////////
1429 // value access //
1430 //////////////////
1431
1432 /// get a boolean (explicit)
1433 boolean_t get_impl(boolean_t* /*unused*/) const
1434 {
1435 if (JSON_HEDLEY_LIKELY(is_boolean()))
1436 {
1437 return m_data.m_value.boolean;
1438 }
1439
1440 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
1441 }
1442
1443 /// get a pointer to the value (object)
1444 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
1445 {
1446 return is_object() ? m_data.m_value.object : nullptr;
1447 }
1448
1449 /// get a pointer to the value (object)
1450 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
1451 {
1452 return is_object() ? m_data.m_value.object : nullptr;
1453 }
1454
1455 /// get a pointer to the value (array)
1456 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
1457 {
1458 return is_array() ? m_data.m_value.array : nullptr;
1459 }
1460
1461 /// get a pointer to the value (array)
1462 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
1463 {
1464 return is_array() ? m_data.m_value.array : nullptr;
1465 }
1466
1467 /// get a pointer to the value (string)
1468 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
1469 {
1470 return is_string() ? m_data.m_value.string : nullptr;
1471 }
1472
1473 /// get a pointer to the value (string)
1474 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
1475 {
1476 return is_string() ? m_data.m_value.string : nullptr;
1477 }
1478
1479 /// get a pointer to the value (boolean)
1480 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
1481 {
1482 return is_boolean() ? &m_data.m_value.boolean : nullptr;
1483 }
1484
1485 /// get a pointer to the value (boolean)
1486 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
1487 {
1488 return is_boolean() ? &m_data.m_value.boolean : nullptr;
1489 }
1490
1491 /// get a pointer to the value (integer number)
1492 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
1493 {
1494 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
1495 }
1496
1497 /// get a pointer to the value (integer number)
1498 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
1499 {
1500 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
1501 }
1502
1503 /// get a pointer to the value (unsigned number)
1504 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
1505 {
1506 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
1507 }
1508
1509 /// get a pointer to the value (unsigned number)
1510 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
1511 {
1512 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
1513 }
1514
1515 /// get a pointer to the value (floating-point number)
1516 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
1517 {
1518 return is_number_float() ? &m_data.m_value.number_float : nullptr;
1519 }
1520
1521 /// get a pointer to the value (floating-point number)
1522 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
1523 {
1524 return is_number_float() ? &m_data.m_value.number_float : nullptr;
1525 }
1526
1527 /// get a pointer to the value (binary)
1528 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
1529 {
1530 return is_binary() ? m_data.m_value.binary : nullptr;
1531 }
1532
1533 /// get a pointer to the value (binary)
1534 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
1535 {
1536 return is_binary() ? m_data.m_value.binary : nullptr;
1537 }
1538
1539 /*!
1540 @brief helper function to implement get_ref()
1541
1542 This function helps to implement get_ref() without code duplication for
1543 const and non-const overloads
1544
1545 @tparam ThisType will be deduced as `basic_json` or `const basic_json`
1546
1547 @throw type_error.303 if ReferenceType does not match underlying value
1548 type of the current JSON
1549 */
1550 template<typename ReferenceType, typename ThisType>
1551 static ReferenceType get_ref_impl(ThisType& obj)
1552 {
1553 // delegate the call to get_ptr<>()
1554 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
1555
1556 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
1557 {
1558 return *ptr;
1559 }
1560
1561 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
1562 }
1563
1564 public:
1565 /// @name value access
1566 /// Direct access to the stored value of a JSON value.
1567 /// @{
1568
1569 /// @brief get a pointer value (implicit)
1570 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1571 template<typename PointerType, typename std::enable_if<
1572 std::is_pointer<PointerType>::value, int>::type = 0>
1573 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1574 {
1575 // delegate the call to get_impl_ptr<>()
1576 return get_impl_ptr(static_cast<PointerType>(nullptr));
1577 }
1578
1579 /// @brief get a pointer value (implicit)
1580 /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1581 template < typename PointerType, typename std::enable_if <
1582 std::is_pointer<PointerType>::value&&
1583 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
1584 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1585 {
1586 // delegate the call to get_impl_ptr<>() const
1587 return get_impl_ptr(static_cast<PointerType>(nullptr));
1588 }
1589
1590 private:
1591 /*!
1592 @brief get a value (explicit)
1593
1594 Explicit type conversion between the JSON value and a compatible value
1595 which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1596 and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1597 The value is converted by calling the @ref json_serializer<ValueType>
1598 `from_json()` method.
1599
1600 The function is equivalent to executing
1601 @code {.cpp}
1602 ValueType ret;
1603 JSONSerializer<ValueType>::from_json(*this, ret);
1604 return ret;
1605 @endcode
1606
1607 This overloads is chosen if:
1608 - @a ValueType is not @ref basic_json,
1609 - @ref json_serializer<ValueType> has a `from_json()` method of the form
1610 `void from_json(const basic_json&, ValueType&)`, and
1611 - @ref json_serializer<ValueType> does not have a `from_json()` method of
1612 the form `ValueType from_json(const basic_json&)`
1613
1614 @tparam ValueType the returned value type
1615
1616 @return copy of the JSON value, converted to @a ValueType
1617
1618 @throw what @ref json_serializer<ValueType> `from_json()` method throws
1619
1620 @liveexample{The example below shows several conversions from JSON values
1621 to other types. There a few things to note: (1) Floating-point numbers can
1622 be converted to integers\, (2) A JSON array can be converted to a standard
1623 `std::vector<short>`\, (3) A JSON object can be converted to C++
1624 associative containers such as `std::unordered_map<std::string\,
1625 json>`.,get__ValueType_const}
1626
1627 @since version 2.1.0
1628 */
1629 template < typename ValueType,
1630 detail::enable_if_t <
1633 int > = 0 >
1634 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
1635 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
1636 {
1637 auto ret = ValueType();
1638 JSONSerializer<ValueType>::from_json(*this, ret);
1639 return ret;
1640 }
1641
1642 /*!
1643 @brief get a value (explicit); special case
1644
1645 Explicit type conversion between the JSON value and a compatible value
1646 which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1647 and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1648 The value is converted by calling the @ref json_serializer<ValueType>
1649 `from_json()` method.
1650
1651 The function is equivalent to executing
1652 @code {.cpp}
1653 return JSONSerializer<ValueType>::from_json(*this);
1654 @endcode
1655
1656 This overloads is chosen if:
1657 - @a ValueType is not @ref basic_json and
1658 - @ref json_serializer<ValueType> has a `from_json()` method of the form
1659 `ValueType from_json(const basic_json&)`
1660
1661 @note If @ref json_serializer<ValueType> has both overloads of
1662 `from_json()`, this one is chosen.
1663
1664 @tparam ValueType the returned value type
1665
1666 @return copy of the JSON value, converted to @a ValueType
1667
1668 @throw what @ref json_serializer<ValueType> `from_json()` method throws
1669
1670 @since version 2.1.0
1671 */
1672 template < typename ValueType,
1673 detail::enable_if_t <
1675 int > = 0 >
1676 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
1677 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
1678 {
1679 return JSONSerializer<ValueType>::from_json(*this);
1680 }
1681
1682 /*!
1683 @brief get special-case overload
1684
1685 This overloads converts the current @ref basic_json in a different
1686 @ref basic_json type
1687
1688 @tparam BasicJsonType == @ref basic_json
1689
1690 @return a copy of *this, converted into @a BasicJsonType
1691
1692 @complexity Depending on the implementation of the called `from_json()`
1693 method.
1694
1695 @since version 3.2.0
1696 */
1697 template < typename BasicJsonType,
1698 detail::enable_if_t <
1700 int > = 0 >
1701 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
1702 {
1703 return *this;
1704 }
1705
1706 /*!
1707 @brief get special-case overload
1708
1709 This overloads avoids a lot of template boilerplate, it can be seen as the
1710 identity method
1711
1712 @tparam BasicJsonType == @ref basic_json
1713
1714 @return a copy of *this
1715
1716 @complexity Constant.
1717
1718 @since version 2.1.0
1719 */
1720 template<typename BasicJsonType,
1721 detail::enable_if_t<
1722 std::is_same<BasicJsonType, basic_json_t>::value,
1723 int> = 0>
1724 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
1725 {
1726 return *this;
1727 }
1728
1729 /*!
1730 @brief get a pointer value (explicit)
1731 @copydoc get()
1732 */
1733 template<typename PointerType,
1734 detail::enable_if_t<
1735 std::is_pointer<PointerType>::value,
1736 int> = 0>
1737 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
1738 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
1739 {
1740 // delegate the call to get_ptr
1741 return get_ptr<PointerType>();
1742 }
1743
1744 public:
1745 /*!
1746 @brief get a (pointer) value (explicit)
1747
1748 Performs explicit type conversion between the JSON value and a compatible value if required.
1749
1750 - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
1751 No copies are made.
1752
1753 - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
1754 from the current @ref basic_json.
1755
1756 - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
1757 method.
1758
1759 @tparam ValueTypeCV the provided value type
1760 @tparam ValueType the returned value type
1761
1762 @return copy of the JSON value, converted to @tparam ValueType if necessary
1763
1764 @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
1765
1766 @since version 2.1.0
1767 */
1768 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
1769#if defined(JSON_HAS_CPP_14)
1770 constexpr
1771#endif
1772 auto get() const noexcept(
1773 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
1774 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
1775 {
1776 // we cannot static_assert on ValueTypeCV being non-const, because
1777 // there is support for get<const basic_json_t>(), which is why we
1778 // still need the uncvref
1779 static_assert(!std::is_reference<ValueTypeCV>::value,
1780 "get() cannot be used with reference types, you might want to use get_ref()");
1781 return get_impl<ValueType>(detail::priority_tag<4> {});
1782 }
1783
1784 /*!
1785 @brief get a pointer value (explicit)
1786
1787 Explicit pointer access to the internally stored JSON value. No copies are
1788 made.
1789
1790 @warning The pointer becomes invalid if the underlying JSON object
1791 changes.
1792
1793 @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
1794 object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
1795 @ref number_unsigned_t, or @ref number_float_t.
1796
1797 @return pointer to the internally stored JSON value if the requested
1798 pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
1799
1800 @complexity Constant.
1801
1802 @liveexample{The example below shows how pointers to internal values of a
1803 JSON value can be requested. Note that no type conversions are made and a
1804 `nullptr` is returned if the value and the requested pointer type does not
1805 match.,get__PointerType}
1806
1807 @sa see @ref get_ptr() for explicit pointer-member access
1808
1809 @since version 1.0.0
1810 */
1811 template<typename PointerType, typename std::enable_if<
1812 std::is_pointer<PointerType>::value, int>::type = 0>
1813 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
1814 {
1815 // delegate the call to get_ptr
1816 return get_ptr<PointerType>();
1817 }
1818
1819 /// @brief get a value (explicit)
1820 /// @sa https://json.nlohmann.me/api/basic_json/get_to/
1821 template < typename ValueType,
1822 detail::enable_if_t <
1825 int > = 0 >
1826 ValueType & get_to(ValueType& v) const noexcept(noexcept(
1827 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
1828 {
1829 JSONSerializer<ValueType>::from_json(*this, v);
1830 return v;
1831 }
1832
1833 // specialization to allow calling get_to with a basic_json value
1834 // see https://github.com/nlohmann/json/issues/2175
1835 template<typename ValueType,
1836 detail::enable_if_t <
1838 int> = 0>
1839 ValueType & get_to(ValueType& v) const
1840 {
1841 v = *this;
1842 return v;
1843 }
1844
1845 template <
1846 typename T, std::size_t N,
1847 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1848 detail::enable_if_t <
1850 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1851 noexcept(noexcept(JSONSerializer<Array>::from_json(
1852 std::declval<const basic_json_t&>(), v)))
1853 {
1854 JSONSerializer<Array>::from_json(*this, v);
1855 return v;
1856 }
1857
1858 /// @brief get a reference value (implicit)
1859 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1860 template<typename ReferenceType, typename std::enable_if<
1861 std::is_reference<ReferenceType>::value, int>::type = 0>
1862 ReferenceType get_ref()
1863 {
1864 // delegate call to get_ref_impl
1865 return get_ref_impl<ReferenceType>(*this);
1866 }
1867
1868 /// @brief get a reference value (implicit)
1869 /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1870 template < typename ReferenceType, typename std::enable_if <
1871 std::is_reference<ReferenceType>::value&&
1872 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
1873 ReferenceType get_ref() const
1874 {
1875 // delegate call to get_ref_impl
1876 return get_ref_impl<ReferenceType>(*this);
1877 }
1878
1879 /*!
1880 @brief get a value (implicit)
1881
1882 Implicit type conversion between the JSON value and a compatible value.
1883 The call is realized by calling @ref get() const.
1884
1885 @tparam ValueType non-pointer type compatible to the JSON value, for
1886 instance `int` for JSON integer numbers, `bool` for JSON booleans, or
1887 `std::vector` types for JSON arrays. The character type of @ref string_t
1888 as well as an initializer list of this type is excluded to avoid
1889 ambiguities as these types implicitly convert to `std::string`.
1890
1891 @return copy of the JSON value, converted to type @a ValueType
1892
1893 @throw type_error.302 in case passed type @a ValueType is incompatible
1894 to the JSON value type (e.g., the JSON value is of type boolean, but a
1895 string is requested); see example below
1896
1897 @complexity Linear in the size of the JSON value.
1898
1899 @liveexample{The example below shows several conversions from JSON values
1900 to other types. There a few things to note: (1) Floating-point numbers can
1901 be converted to integers\, (2) A JSON array can be converted to a standard
1902 `std::vector<short>`\, (3) A JSON object can be converted to C++
1903 associative containers such as `std::unordered_map<std::string\,
1904 json>`.,operator__ValueType}
1905
1906 @since version 1.0.0
1907 */
1908 template < typename ValueType, typename std::enable_if <
1916#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
1918#endif
1919#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
1921#endif
1923 >::value, int >::type = 0 >
1924 JSON_EXPLICIT operator ValueType() const
1925 {
1926 // delegate the call to get<>() const
1927 return get<ValueType>();
1928 }
1929
1930 /// @brief get a binary value
1931 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
1933 {
1934 if (!is_binary())
1935 {
1936 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1937 }
1938
1939 return *get_ptr<binary_t*>();
1940 }
1941
1942 /// @brief get a binary value
1943 /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
1944 const binary_t& get_binary() const
1945 {
1946 if (!is_binary())
1947 {
1948 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1949 }
1950
1951 return *get_ptr<const binary_t*>();
1952 }
1953
1954 /// @}
1955
1956 ////////////////////
1957 // element access //
1958 ////////////////////
1959
1960 /// @name element access
1961 /// Access to the JSON value.
1962 /// @{
1963
1964 /// @brief access specified array element with bounds checking
1965 /// @sa https://json.nlohmann.me/api/basic_json/at/
1967 {
1968 // at only works for arrays
1969 if (JSON_HEDLEY_LIKELY(is_array()))
1970 {
1971 JSON_TRY
1972 {
1973 return set_parent(m_data.m_value.array->at(idx));
1974 }
1975 JSON_CATCH (std::out_of_range&)
1976 {
1977 // create a better exception explanation
1978 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
1979 } // cppcheck-suppress[missingReturn]
1980 }
1981 else
1982 {
1983 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1984 }
1985 }
1986
1987 /// @brief access specified array element with bounds checking
1988 /// @sa https://json.nlohmann.me/api/basic_json/at/
1990 {
1991 // at only works for arrays
1992 if (JSON_HEDLEY_LIKELY(is_array()))
1993 {
1994 JSON_TRY
1995 {
1996 return m_data.m_value.array->at(idx);
1997 }
1998 JSON_CATCH (std::out_of_range&)
1999 {
2000 // create a better exception explanation
2001 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
2002 } // cppcheck-suppress[missingReturn]
2003 }
2004 else
2005 {
2006 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2007 }
2008 }
2009
2010 /// @brief access specified object element with bounds checking
2011 /// @sa https://json.nlohmann.me/api/basic_json/at/
2012 reference at(const typename object_t::key_type& key)
2013 {
2014 // at only works for objects
2015 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2016 {
2017 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2018 }
2019
2020 auto it = m_data.m_value.object->find(key);
2021 if (it == m_data.m_value.object->end())
2022 {
2023 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
2024 }
2025 return set_parent(it->second);
2026 }
2027
2028 /// @brief access specified object element with bounds checking
2029 /// @sa https://json.nlohmann.me/api/basic_json/at/
2030 template<class KeyType, detail::enable_if_t<
2031 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2032 reference at(KeyType && key)
2033 {
2034 // at only works for objects
2035 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2036 {
2037 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2038 }
2039
2040 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2041 if (it == m_data.m_value.object->end())
2042 {
2043 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2044 }
2045 return set_parent(it->second);
2046 }
2047
2048 /// @brief access specified object element with bounds checking
2049 /// @sa https://json.nlohmann.me/api/basic_json/at/
2050 const_reference at(const typename object_t::key_type& key) const
2051 {
2052 // at only works for objects
2053 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2054 {
2055 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2056 }
2057
2058 auto it = m_data.m_value.object->find(key);
2059 if (it == m_data.m_value.object->end())
2060 {
2061 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
2062 }
2063 return it->second;
2064 }
2065
2066 /// @brief access specified object element with bounds checking
2067 /// @sa https://json.nlohmann.me/api/basic_json/at/
2068 template<class KeyType, detail::enable_if_t<
2069 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2070 const_reference at(KeyType && key) const
2071 {
2072 // at only works for objects
2073 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2074 {
2075 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2076 }
2077
2078 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2079 if (it == m_data.m_value.object->end())
2080 {
2081 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2082 }
2083 return it->second;
2084 }
2085
2086 /// @brief access specified array element
2087 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2089 {
2090 // implicitly convert a null value to an empty array
2091 if (is_null())
2092 {
2093 m_data.m_type = value_t::array;
2094 m_data.m_value.array = create<array_t>();
2095 assert_invariant();
2096 }
2097
2098 // operator[] only works for arrays
2099 if (JSON_HEDLEY_LIKELY(is_array()))
2100 {
2101 // fill up the array with null values if given idx is outside the range
2102 if (idx >= m_data.m_value.array->size())
2103 {
2104#if JSON_DIAGNOSTICS
2105 // remember array size & capacity before resizing
2106 const auto old_size = m_data.m_value.array->size();
2107 const auto old_capacity = m_data.m_value.array->capacity();
2108#endif
2109 m_data.m_value.array->resize(idx + 1);
2110
2111#if JSON_DIAGNOSTICS
2112 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
2113 {
2114 // capacity has changed: update all parents
2115 set_parents();
2116 }
2117 else
2118 {
2119 // set parent for values added above
2120 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
2121 }
2122#endif
2123 assert_invariant();
2124 }
2125
2126 return m_data.m_value.array->operator[](idx);
2127 }
2128
2129 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2130 }
2131
2132 /// @brief access specified array element
2133 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2135 {
2136 // const operator[] only works for arrays
2137 if (JSON_HEDLEY_LIKELY(is_array()))
2138 {
2139 return m_data.m_value.array->operator[](idx);
2140 }
2141
2142 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2143 }
2144
2145 /// @brief access specified object element
2146 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2147 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
2148 {
2149 // implicitly convert a null value to an empty object
2150 if (is_null())
2151 {
2152 m_data.m_type = value_t::object;
2153 m_data.m_value.object = create<object_t>();
2154 assert_invariant();
2155 }
2156
2157 // operator[] only works for objects
2158 if (JSON_HEDLEY_LIKELY(is_object()))
2159 {
2160 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
2161 return set_parent(result.first->second);
2162 }
2163
2164 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2165 }
2166
2167 /// @brief access specified object element
2168 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2169 const_reference operator[](const typename object_t::key_type& key) const
2170 {
2171 // const operator[] only works for objects
2172 if (JSON_HEDLEY_LIKELY(is_object()))
2173 {
2174 auto it = m_data.m_value.object->find(key);
2175 JSON_ASSERT(it != m_data.m_value.object->end());
2176 return it->second;
2177 }
2178
2179 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2180 }
2181
2182 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
2183 // (they seemingly cannot be constrained to resolve the ambiguity)
2184 template<typename T>
2185 reference operator[](T* key)
2186 {
2187 return operator[](typename object_t::key_type(key));
2188 }
2189
2190 template<typename T>
2191 const_reference operator[](T* key) const
2192 {
2193 return operator[](typename object_t::key_type(key));
2194 }
2195
2196 /// @brief access specified object element
2197 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2198 template<class KeyType, detail::enable_if_t<
2199 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
2200 reference operator[](KeyType && key)
2201 {
2202 // implicitly convert a null value to an empty object
2203 if (is_null())
2204 {
2205 m_data.m_type = value_t::object;
2206 m_data.m_value.object = create<object_t>();
2207 assert_invariant();
2208 }
2209
2210 // operator[] only works for objects
2211 if (JSON_HEDLEY_LIKELY(is_object()))
2212 {
2213 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
2214 return set_parent(result.first->second);
2215 }
2216
2217 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2218 }
2219
2220 /// @brief access specified object element
2221 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2222 template<class KeyType, detail::enable_if_t<
2223 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
2224 const_reference operator[](KeyType && key) const
2225 {
2226 // const operator[] only works for objects
2227 if (JSON_HEDLEY_LIKELY(is_object()))
2228 {
2229 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2230 JSON_ASSERT(it != m_data.m_value.object->end());
2231 return it->second;
2232 }
2233
2234 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2235 }
2236
2237 private:
2238 template<typename KeyType>
2239 using is_comparable_with_object_key = detail::is_comparable <
2240 object_comparator_t, const typename object_t::key_type&, KeyType >;
2241
2242 template<typename ValueType>
2243 using value_return_type = std::conditional <
2244 detail::is_c_string_uncvref<ValueType>::value,
2245 string_t, typename std::decay<ValueType>::type >;
2246
2247 public:
2248 /// @brief access specified object element with default value
2249 /// @sa https://json.nlohmann.me/api/basic_json/value/
2250 template < class ValueType, detail::enable_if_t <
2252 && detail::is_getable<basic_json_t, ValueType>::value
2253 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2254 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
2255 {
2256 // value only works for objects
2257 if (JSON_HEDLEY_LIKELY(is_object()))
2258 {
2259 // If 'key' is found, return its value. Otherwise, return `default_value'.
2260 const auto it = find(key);
2261 if (it != end())
2262 {
2263 return it->template get<ValueType>();
2264 }
2265
2266 return default_value;
2267 }
2268
2269 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2270 }
2271
2272 /// @brief access specified object element with default value
2273 /// @sa https://json.nlohmann.me/api/basic_json/value/
2274 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2275 detail::enable_if_t <
2277 && detail::is_getable<basic_json_t, ReturnType>::value
2278 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2279 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
2280 {
2281 // value only works for objects
2282 if (JSON_HEDLEY_LIKELY(is_object()))
2283 {
2284 // If 'key' is found, return its value. Otherwise, return `default_value'.
2285 const auto it = find(key);
2286 if (it != end())
2287 {
2288 return it->template get<ReturnType>();
2289 }
2290
2291 return std::forward<ValueType>(default_value);
2292 }
2293
2294 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2295 }
2296
2297 /// @brief access specified object element with default value
2298 /// @sa https://json.nlohmann.me/api/basic_json/value/
2299 template < class ValueType, class KeyType, detail::enable_if_t <
2301 && !detail::is_json_pointer<KeyType>::value
2302 && is_comparable_with_object_key<KeyType>::value
2303 && detail::is_getable<basic_json_t, ValueType>::value
2304 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2305 ValueType value(KeyType && key, const ValueType& default_value) const
2306 {
2307 // value only works for objects
2308 if (JSON_HEDLEY_LIKELY(is_object()))
2309 {
2310 // If 'key' is found, return its value. Otherwise, return `default_value'.
2311 const auto it = find(std::forward<KeyType>(key));
2312 if (it != end())
2313 {
2314 return it->template get<ValueType>();
2315 }
2316
2317 return default_value;
2318 }
2319
2320 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2321 }
2322
2323 /// @brief access specified object element via JSON Pointer with default value
2324 /// @sa https://json.nlohmann.me/api/basic_json/value/
2325 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
2326 detail::enable_if_t <
2328 && !detail::is_json_pointer<KeyType>::value
2329 && is_comparable_with_object_key<KeyType>::value
2330 && detail::is_getable<basic_json_t, ReturnType>::value
2331 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2332 ReturnType value(KeyType && key, ValueType && default_value) const
2333 {
2334 // value only works for objects
2335 if (JSON_HEDLEY_LIKELY(is_object()))
2336 {
2337 // If 'key' is found, return its value. Otherwise, return `default_value'.
2338 const auto it = find(std::forward<KeyType>(key));
2339 if (it != end())
2340 {
2341 return it->template get<ReturnType>();
2342 }
2343
2344 return std::forward<ValueType>(default_value);
2345 }
2346
2347 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2348 }
2349
2350 /// @brief access specified object element via JSON Pointer with default value
2351 /// @sa https://json.nlohmann.me/api/basic_json/value/
2352 template < class ValueType, detail::enable_if_t <
2353 detail::is_getable<basic_json_t, ValueType>::value
2354 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2355 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
2356 {
2357 // value only works for objects
2358 if (JSON_HEDLEY_LIKELY(is_object()))
2359 {
2360 // If the pointer resolves to a value, return it. Otherwise, return
2361 // 'default_value'.
2362 JSON_TRY
2363 {
2364 return ptr.get_checked(this).template get<ValueType>();
2365 }
2366 JSON_INTERNAL_CATCH (out_of_range&)
2367 {
2368 return default_value;
2369 }
2370 }
2371
2372 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2373 }
2374
2375 /// @brief access specified object element via JSON Pointer with default value
2376 /// @sa https://json.nlohmann.me/api/basic_json/value/
2377 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2378 detail::enable_if_t <
2379 detail::is_getable<basic_json_t, ReturnType>::value
2380 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2381 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
2382 {
2383 // value only works for objects
2384 if (JSON_HEDLEY_LIKELY(is_object()))
2385 {
2386 // If the pointer resolves to a value, return it. Otherwise, return
2387 // 'default_value'.
2388 JSON_TRY
2389 {
2390 return ptr.get_checked(this).template get<ReturnType>();
2391 }
2392 JSON_INTERNAL_CATCH (out_of_range&)
2393 {
2394 return std::forward<ValueType>(default_value);
2395 }
2396 }
2397
2398 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2399 }
2400
2401 template < class ValueType, class BasicJsonType, detail::enable_if_t <
2403 && detail::is_getable<basic_json_t, ValueType>::value
2404 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2405 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2406 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
2407 {
2408 return value(ptr.convert(), default_value);
2409 }
2410
2411 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
2412 detail::enable_if_t <
2414 && detail::is_getable<basic_json_t, ReturnType>::value
2415 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2416 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2417 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
2418 {
2419 return value(ptr.convert(), std::forward<ValueType>(default_value));
2420 }
2421
2422 /// @brief access the first element
2423 /// @sa https://json.nlohmann.me/api/basic_json/front/
2425 {
2426 return *begin();
2427 }
2428
2429 /// @brief access the first element
2430 /// @sa https://json.nlohmann.me/api/basic_json/front/
2432 {
2433 return *cbegin();
2434 }
2435
2436 /// @brief access the last element
2437 /// @sa https://json.nlohmann.me/api/basic_json/back/
2439 {
2440 auto tmp = end();
2441 --tmp;
2442 return *tmp;
2443 }
2444
2445 /// @brief access the last element
2446 /// @sa https://json.nlohmann.me/api/basic_json/back/
2448 {
2449 auto tmp = cend();
2450 --tmp;
2451 return *tmp;
2452 }
2453
2454 /// @brief remove element given an iterator
2455 /// @sa https://json.nlohmann.me/api/basic_json/erase/
2456 template < class IteratorType, detail::enable_if_t <
2457 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2458 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
2459 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
2460 {
2461 // make sure the iterator fits the current value
2462 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
2463 {
2464 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
2465 }
2466
2467 IteratorType result = end();
2468
2469 switch (m_data.m_type)
2470 {
2471 case value_t::boolean:
2472 case value_t::number_float:
2473 case value_t::number_integer:
2474 case value_t::number_unsigned:
2475 case value_t::string:
2476 case value_t::binary:
2477 {
2478 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
2479 {
2480 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
2481 }
2482
2483 if (is_string())
2484 {
2485 AllocatorType<string_t> alloc;
2486 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
2487 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
2488 m_data.m_value.string = nullptr;
2489 }
2490 else if (is_binary())
2491 {
2492 AllocatorType<binary_t> alloc;
2493 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
2494 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
2495 m_data.m_value.binary = nullptr;
2496 }
2497
2498 m_data.m_type = value_t::null;
2499 assert_invariant();
2500 break;
2501 }
2502
2503 case value_t::object:
2504 {
2505 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
2506 break;
2507 }
2508
2509 case value_t::array:
2510 {
2511 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
2512 break;
2513 }
2514
2515 case value_t::null:
2516 case value_t::discarded:
2517 default:
2518 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2519 }
2520
2521 return result;
2522 }
2523
2524 /// @brief remove elements given an iterator range
2525 /// @sa https://json.nlohmann.me/api/basic_json/erase/
2526 template < class IteratorType, detail::enable_if_t <
2527 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2528 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
2529 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
2530 {
2531 // make sure the iterator fits the current value
2532 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
2533 {
2534 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
2535 }
2536
2537 IteratorType result = end();
2538
2539 switch (m_data.m_type)
2540 {
2541 case value_t::boolean:
2542 case value_t::number_float:
2543 case value_t::number_integer:
2544 case value_t::number_unsigned:
2545 case value_t::string:
2546 case value_t::binary:
2547 {
2548 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
2549 || !last.m_it.primitive_iterator.is_end()))
2550 {
2551 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
2552 }
2553
2554 if (is_string())
2555 {
2556 AllocatorType<string_t> alloc;
2557 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
2558 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
2559 m_data.m_value.string = nullptr;
2560 }
2561 else if (is_binary())
2562 {
2563 AllocatorType<binary_t> alloc;
2564 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
2565 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
2566 m_data.m_value.binary = nullptr;
2567 }
2568
2569 m_data.m_type = value_t::null;
2570 assert_invariant();
2571 break;
2572 }
2573
2574 case value_t::object:
2575 {
2576 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
2577 last.m_it.object_iterator);
2578 break;
2579 }
2580
2581 case value_t::array:
2582 {
2583 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
2584 last.m_it.array_iterator);
2585 break;
2586 }
2587
2588 case value_t::null:
2589 case value_t::discarded:
2590 default:
2591 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2592 }
2593
2594 return result;
2595 }
2596
2597 private:
2598 template < typename KeyType, detail::enable_if_t <
2599 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
2600 size_type erase_internal(KeyType && key)
2601 {
2602 // this erase only works for objects
2603 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2604 {
2605 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2606 }
2607
2608 return m_data.m_value.object->erase(std::forward<KeyType>(key));
2609 }
2610
2611 template < typename KeyType, detail::enable_if_t <
2612 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
2613 size_type erase_internal(KeyType && key)
2614 {
2615 // this erase only works for objects
2616 if (JSON_HEDLEY_UNLIKELY(!is_object()))
2617 {
2618 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2619 }
2620
2621 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2622 if (it != m_data.m_value.object->end())
2623 {
2624 m_data.m_value.object->erase(it);
2625 return 1;
2626 }
2627 return 0;
2628 }
2629
2630 public:
2631
2632 /// @brief remove element from a JSON object given a key
2633 /// @sa https://json.nlohmann.me/api/basic_json/erase/
2634 size_type erase(const typename object_t::key_type& key)
2635 {
2636 // the indirection via erase_internal() is added to avoid making this
2637 // function a template and thus de-rank it during overload resolution
2638 return erase_internal(key);
2639 }
2640
2641 /// @brief remove element from a JSON object given a key
2642 /// @sa https://json.nlohmann.me/api/basic_json/erase/
2643 template<class KeyType, detail::enable_if_t<
2644 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2645 size_type erase(KeyType && key)
2646 {
2647 return erase_internal(std::forward<KeyType>(key));
2648 }
2649
2650 /// @brief remove element from a JSON array given an index
2651 /// @sa https://json.nlohmann.me/api/basic_json/erase/
2652 void erase(const size_type idx)
2653 {
2654 // this erase only works for arrays
2655 if (JSON_HEDLEY_LIKELY(is_array()))
2656 {
2657 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
2658 {
2659 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
2660 }
2661
2662 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
2663 }
2664 else
2665 {
2666 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2667 }
2668 }
2669
2670 /// @}
2671
2672 ////////////
2673 // lookup //
2674 ////////////
2675
2676 /// @name lookup
2677 /// @{
2678
2679 /// @brief find an element in a JSON object
2680 /// @sa https://json.nlohmann.me/api/basic_json/find/
2681 iterator find(const typename object_t::key_type& key)
2682 {
2683 auto result = end();
2684
2685 if (is_object())
2686 {
2687 result.m_it.object_iterator = m_data.m_value.object->find(key);
2688 }
2689
2690 return result;
2691 }
2692
2693 /// @brief find an element in a JSON object
2694 /// @sa https://json.nlohmann.me/api/basic_json/find/
2695 const_iterator find(const typename object_t::key_type& key) const
2696 {
2697 auto result = cend();
2698
2699 if (is_object())
2700 {
2701 result.m_it.object_iterator = m_data.m_value.object->find(key);
2702 }
2703
2704 return result;
2705 }
2706
2707 /// @brief find an element in a JSON object
2708 /// @sa https://json.nlohmann.me/api/basic_json/find/
2709 template<class KeyType, detail::enable_if_t<
2710 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2711 iterator find(KeyType && key)
2712 {
2713 auto result = end();
2714
2715 if (is_object())
2716 {
2717 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
2718 }
2719
2720 return result;
2721 }
2722
2723 /// @brief find an element in a JSON object
2724 /// @sa https://json.nlohmann.me/api/basic_json/find/
2725 template<class KeyType, detail::enable_if_t<
2726 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2727 const_iterator find(KeyType && key) const
2728 {
2729 auto result = cend();
2730
2731 if (is_object())
2732 {
2733 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
2734 }
2735
2736 return result;
2737 }
2738
2739 /// @brief returns the number of occurrences of a key in a JSON object
2740 /// @sa https://json.nlohmann.me/api/basic_json/count/
2741 size_type count(const typename object_t::key_type& key) const
2742 {
2743 // return 0 for all nonobject types
2744 return is_object() ? m_data.m_value.object->count(key) : 0;
2745 }
2746
2747 /// @brief returns the number of occurrences of a key in a JSON object
2748 /// @sa https://json.nlohmann.me/api/basic_json/count/
2749 template<class KeyType, detail::enable_if_t<
2750 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2751 size_type count(KeyType && key) const
2752 {
2753 // return 0 for all nonobject types
2754 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
2755 }
2756
2757 /// @brief check the existence of an element in a JSON object
2758 /// @sa https://json.nlohmann.me/api/basic_json/contains/
2759 bool contains(const typename object_t::key_type& key) const
2760 {
2761 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
2762 }
2763
2764 /// @brief check the existence of an element in a JSON object
2765 /// @sa https://json.nlohmann.me/api/basic_json/contains/
2766 template<class KeyType, detail::enable_if_t<
2767 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2768 bool contains(KeyType && key) const
2769 {
2770 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
2771 }
2772
2773 /// @brief check the existence of an element in a JSON object given a JSON pointer
2774 /// @sa https://json.nlohmann.me/api/basic_json/contains/
2775 bool contains(const json_pointer& ptr) const
2776 {
2777 return ptr.contains(this);
2778 }
2779
2780 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
2781 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2782 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
2783 {
2784 return ptr.contains(this);
2785 }
2786
2787 /// @}
2788
2789 ///////////////
2790 // iterators //
2791 ///////////////
2792
2793 /// @name iterators
2794 /// @{
2795
2796 /// @brief returns an iterator to the first element
2797 /// @sa https://json.nlohmann.me/api/basic_json/begin/
2798 iterator begin() noexcept
2799 {
2800 iterator result(this);
2801 result.set_begin();
2802 return result;
2803 }
2804
2805 /// @brief returns an iterator to the first element
2806 /// @sa https://json.nlohmann.me/api/basic_json/begin/
2807 const_iterator begin() const noexcept
2808 {
2809 return cbegin();
2810 }
2811
2812 /// @brief returns a const iterator to the first element
2813 /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
2814 const_iterator cbegin() const noexcept
2815 {
2816 const_iterator result(this);
2817 result.set_begin();
2818 return result;
2819 }
2820
2821 /// @brief returns an iterator to one past the last element
2822 /// @sa https://json.nlohmann.me/api/basic_json/end/
2823 iterator end() noexcept
2824 {
2825 iterator result(this);
2826 result.set_end();
2827 return result;
2828 }
2829
2830 /// @brief returns an iterator to one past the last element
2831 /// @sa https://json.nlohmann.me/api/basic_json/end/
2832 const_iterator end() const noexcept
2833 {
2834 return cend();
2835 }
2836
2837 /// @brief returns an iterator to one past the last element
2838 /// @sa https://json.nlohmann.me/api/basic_json/cend/
2839 const_iterator cend() const noexcept
2840 {
2841 const_iterator result(this);
2842 result.set_end();
2843 return result;
2844 }
2845
2846 /// @brief returns an iterator to the reverse-beginning
2847 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2849 {
2850 return reverse_iterator(end());
2851 }
2852
2853 /// @brief returns an iterator to the reverse-beginning
2854 /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2856 {
2857 return crbegin();
2858 }
2859
2860 /// @brief returns an iterator to the reverse-end
2861 /// @sa https://json.nlohmann.me/api/basic_json/rend/
2863 {
2864 return reverse_iterator(begin());
2865 }
2866
2867 /// @brief returns an iterator to the reverse-end
2868 /// @sa https://json.nlohmann.me/api/basic_json/rend/
2870 {
2871 return crend();
2872 }
2873
2874 /// @brief returns a const reverse iterator to the last element
2875 /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
2877 {
2878 return const_reverse_iterator(cend());
2879 }
2880
2881 /// @brief returns a const reverse iterator to one before the first
2882 /// @sa https://json.nlohmann.me/api/basic_json/crend/
2884 {
2886 }
2887
2888 public:
2889 /// @brief wrapper to access iterator member functions in range-based for
2890 /// @sa https://json.nlohmann.me/api/basic_json/items/
2891 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2892 /// version 4.0.0 of the library. Please use @ref items() instead;
2893 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2894 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2895 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
2896 {
2897 return ref.items();
2898 }
2899
2900 /// @brief wrapper to access iterator member functions in range-based for
2901 /// @sa https://json.nlohmann.me/api/basic_json/items/
2902 /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2903 /// version 4.0.0 of the library. Please use @ref items() instead;
2904 /// that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2905 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2906 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
2907 {
2908 return ref.items();
2909 }
2910
2911 /// @brief helper to access iterator member functions in range-based for
2912 /// @sa https://json.nlohmann.me/api/basic_json/items/
2913 iteration_proxy<iterator> items() noexcept
2914 {
2915 return iteration_proxy<iterator>(*this);
2916 }
2917
2918 /// @brief helper to access iterator member functions in range-based for
2919 /// @sa https://json.nlohmann.me/api/basic_json/items/
2920 iteration_proxy<const_iterator> items() const noexcept
2921 {
2922 return iteration_proxy<const_iterator>(*this);
2923 }
2924
2925 /// @}
2926
2927 //////////////
2928 // capacity //
2929 //////////////
2930
2931 /// @name capacity
2932 /// @{
2933
2934 /// @brief checks whether the container is empty.
2935 /// @sa https://json.nlohmann.me/api/basic_json/empty/
2936 bool empty() const noexcept
2937 {
2938 switch (m_data.m_type)
2939 {
2940 case value_t::null:
2941 {
2942 // null values are empty
2943 return true;
2944 }
2945
2946 case value_t::array:
2947 {
2948 // delegate call to array_t::empty()
2949 return m_data.m_value.array->empty();
2950 }
2951
2952 case value_t::object:
2953 {
2954 // delegate call to object_t::empty()
2955 return m_data.m_value.object->empty();
2956 }
2957
2958 case value_t::string:
2959 case value_t::boolean:
2960 case value_t::number_integer:
2961 case value_t::number_unsigned:
2962 case value_t::number_float:
2963 case value_t::binary:
2964 case value_t::discarded:
2965 default:
2966 {
2967 // all other types are nonempty
2968 return false;
2969 }
2970 }
2971 }
2972
2973 /// @brief returns the number of elements
2974 /// @sa https://json.nlohmann.me/api/basic_json/size/
2975 size_type size() const noexcept
2976 {
2977 switch (m_data.m_type)
2978 {
2979 case value_t::null:
2980 {
2981 // null values are empty
2982 return 0;
2983 }
2984
2985 case value_t::array:
2986 {
2987 // delegate call to array_t::size()
2988 return m_data.m_value.array->size();
2989 }
2990
2991 case value_t::object:
2992 {
2993 // delegate call to object_t::size()
2994 return m_data.m_value.object->size();
2995 }
2996
2997 case value_t::string:
2998 case value_t::boolean:
2999 case value_t::number_integer:
3000 case value_t::number_unsigned:
3001 case value_t::number_float:
3002 case value_t::binary:
3003 case value_t::discarded:
3004 default:
3005 {
3006 // all other types have size 1
3007 return 1;
3008 }
3009 }
3010 }
3011
3012 /// @brief returns the maximum possible number of elements
3013 /// @sa https://json.nlohmann.me/api/basic_json/max_size/
3014 size_type max_size() const noexcept
3015 {
3016 switch (m_data.m_type)
3017 {
3018 case value_t::array:
3019 {
3020 // delegate call to array_t::max_size()
3021 return m_data.m_value.array->max_size();
3022 }
3023
3024 case value_t::object:
3025 {
3026 // delegate call to object_t::max_size()
3027 return m_data.m_value.object->max_size();
3028 }
3029
3030 case value_t::null:
3031 case value_t::string:
3032 case value_t::boolean:
3033 case value_t::number_integer:
3034 case value_t::number_unsigned:
3035 case value_t::number_float:
3036 case value_t::binary:
3037 case value_t::discarded:
3038 default:
3039 {
3040 // all other types have max_size() == size()
3041 return size();
3042 }
3043 }
3044 }
3045
3046 /// @}
3047
3048 ///////////////
3049 // modifiers //
3050 ///////////////
3051
3052 /// @name modifiers
3053 /// @{
3054
3055 /// @brief clears the contents
3056 /// @sa https://json.nlohmann.me/api/basic_json/clear/
3057 void clear() noexcept
3058 {
3059 switch (m_data.m_type)
3060 {
3061 case value_t::number_integer:
3062 {
3063 m_data.m_value.number_integer = 0;
3064 break;
3065 }
3066
3067 case value_t::number_unsigned:
3068 {
3069 m_data.m_value.number_unsigned = 0;
3070 break;
3071 }
3072
3073 case value_t::number_float:
3074 {
3075 m_data.m_value.number_float = 0.0;
3076 break;
3077 }
3078
3079 case value_t::boolean:
3080 {
3081 m_data.m_value.boolean = false;
3082 break;
3083 }
3084
3085 case value_t::string:
3086 {
3087 m_data.m_value.string->clear();
3088 break;
3089 }
3090
3091 case value_t::binary:
3092 {
3093 m_data.m_value.binary->clear();
3094 break;
3095 }
3096
3097 case value_t::array:
3098 {
3099 m_data.m_value.array->clear();
3100 break;
3101 }
3102
3103 case value_t::object:
3104 {
3105 m_data.m_value.object->clear();
3106 break;
3107 }
3108
3109 case value_t::null:
3110 case value_t::discarded:
3111 default:
3112 break;
3113 }
3114 }
3115
3116 /// @brief add an object to an array
3117 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3119 {
3120 // push_back only works for null objects or arrays
3121 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3122 {
3123 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3124 }
3125
3126 // transform a null object into an array
3127 if (is_null())
3128 {
3129 m_data.m_type = value_t::array;
3130 m_data.m_value = value_t::array;
3131 assert_invariant();
3132 }
3133
3134 // add the element to the array (move semantics)
3135 const auto old_capacity = m_data.m_value.array->capacity();
3136 m_data.m_value.array->push_back(std::move(val));
3137 set_parent(m_data.m_value.array->back(), old_capacity);
3138 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
3139 }
3140
3141 /// @brief add an object to an array
3142 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3144 {
3145 push_back(std::move(val));
3146 return *this;
3147 }
3148
3149 /// @brief add an object to an array
3150 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3151 void push_back(const basic_json& val)
3152 {
3153 // push_back only works for null objects or arrays
3154 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3155 {
3156 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3157 }
3158
3159 // transform a null object into an array
3160 if (is_null())
3161 {
3162 m_data.m_type = value_t::array;
3163 m_data.m_value = value_t::array;
3164 assert_invariant();
3165 }
3166
3167 // add the element to the array
3168 const auto old_capacity = m_data.m_value.array->capacity();
3169 m_data.m_value.array->push_back(val);
3170 set_parent(m_data.m_value.array->back(), old_capacity);
3171 }
3172
3173 /// @brief add an object to an array
3174 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3176 {
3177 push_back(val);
3178 return *this;
3179 }
3180
3181 /// @brief add an object to an object
3182 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3183 void push_back(const typename object_t::value_type& val)
3184 {
3185 // push_back only works for null objects or objects
3186 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3187 {
3188 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3189 }
3190
3191 // transform a null object into an object
3192 if (is_null())
3193 {
3194 m_data.m_type = value_t::object;
3195 m_data.m_value = value_t::object;
3196 assert_invariant();
3197 }
3198
3199 // add the element to the object
3200 auto res = m_data.m_value.object->insert(val);
3201 set_parent(res.first->second);
3202 }
3203
3204 /// @brief add an object to an object
3205 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3206 reference operator+=(const typename object_t::value_type& val)
3207 {
3208 push_back(val);
3209 return *this;
3210 }
3211
3212 /// @brief add an object to an object
3213 /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3215 {
3216 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
3217 {
3218 basic_json&& key = init.begin()->moved_or_copied();
3219 push_back(typename object_t::value_type(
3220 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
3221 }
3222 else
3223 {
3224 push_back(basic_json(init));
3225 }
3226 }
3227
3228 /// @brief add an object to an object
3229 /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3231 {
3232 push_back(init);
3233 return *this;
3234 }
3235
3236 /// @brief add an object to an array
3237 /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
3238 template<class... Args>
3239 reference emplace_back(Args&& ... args)
3240 {
3241 // emplace_back only works for null objects or arrays
3242 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3243 {
3244 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
3245 }
3246
3247 // transform a null object into an array
3248 if (is_null())
3249 {
3250 m_data.m_type = value_t::array;
3251 m_data.m_value = value_t::array;
3252 assert_invariant();
3253 }
3254
3255 // add the element to the array (perfect forwarding)
3256 const auto old_capacity = m_data.m_value.array->capacity();
3257 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
3258 return set_parent(m_data.m_value.array->back(), old_capacity);
3259 }
3260
3261 /// @brief add an object to an object if key does not exist
3262 /// @sa https://json.nlohmann.me/api/basic_json/emplace/
3263 template<class... Args>
3264 std::pair<iterator, bool> emplace(Args&& ... args)
3265 {
3266 // emplace only works for null objects or arrays
3267 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3268 {
3269 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
3270 }
3271
3272 // transform a null object into an object
3273 if (is_null())
3274 {
3275 m_data.m_type = value_t::object;
3276 m_data.m_value = value_t::object;
3277 assert_invariant();
3278 }
3279
3280 // add the element to the array (perfect forwarding)
3281 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
3282 set_parent(res.first->second);
3283
3284 // create a result iterator and set iterator to the result of emplace
3285 auto it = begin();
3286 it.m_it.object_iterator = res.first;
3287
3288 // return pair of iterator and boolean
3289 return {it, res.second};
3290 }
3291
3292 /// Helper for insertion of an iterator
3293 /// @note: This uses std::distance to support GCC 4.8,
3294 /// see https://github.com/nlohmann/json/pull/1257
3295 template<typename... Args>
3296 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
3297 {
3298 iterator result(this);
3299 JSON_ASSERT(m_data.m_value.array != nullptr);
3300
3301 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
3302 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
3303 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
3304
3305 // This could have been written as:
3306 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
3307 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
3308
3309 set_parents();
3310 return result;
3311 }
3312
3313 /// @brief inserts element into array
3314 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3315 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
3316 {
3317 // insert only works for arrays
3318 if (JSON_HEDLEY_LIKELY(is_array()))
3319 {
3320 // check if iterator pos fits to this JSON value
3321 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3322 {
3323 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3324 }
3325
3326 // insert to array and return iterator
3327 return insert_iterator(pos, val);
3328 }
3329
3330 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3331 }
3332
3333 /// @brief inserts element into array
3334 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3335 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
3336 {
3337 return insert(pos, val);
3338 }
3339
3340 /// @brief inserts copies of element into array
3341 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3342 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
3343 {
3344 // insert only works for arrays
3345 if (JSON_HEDLEY_LIKELY(is_array()))
3346 {
3347 // check if iterator pos fits to this JSON value
3348 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3349 {
3350 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3351 }
3352
3353 // insert to array and return iterator
3354 return insert_iterator(pos, cnt, val);
3355 }
3356
3357 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3358 }
3359
3360 /// @brief inserts range of elements into array
3361 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3362 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
3363 {
3364 // insert only works for arrays
3365 if (JSON_HEDLEY_UNLIKELY(!is_array()))
3366 {
3367 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3368 }
3369
3370 // check if iterator pos fits to this JSON value
3371 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3372 {
3373 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3374 }
3375
3376 // check if range iterators belong to the same JSON object
3377 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3378 {
3379 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3380 }
3381
3382 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
3383 {
3384 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
3385 }
3386
3387 // insert to array and return iterator
3388 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
3389 }
3390
3391 /// @brief inserts elements from initializer list into array
3392 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3393 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
3394 {
3395 // insert only works for arrays
3396 if (JSON_HEDLEY_UNLIKELY(!is_array()))
3397 {
3398 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3399 }
3400
3401 // check if iterator pos fits to this JSON value
3402 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3403 {
3404 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3405 }
3406
3407 // insert to array and return iterator
3408 return insert_iterator(pos, ilist.begin(), ilist.end());
3409 }
3410
3411 /// @brief inserts range of elements into object
3412 /// @sa https://json.nlohmann.me/api/basic_json/insert/
3413 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
3414 {
3415 // insert only works for objects
3416 if (JSON_HEDLEY_UNLIKELY(!is_object()))
3417 {
3418 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3419 }
3420
3421 // check if range iterators belong to the same JSON object
3422 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3423 {
3424 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3425 }
3426
3427 // passed iterators must belong to objects
3428 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3429 {
3430 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
3431 }
3432
3433 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
3434 set_parents();
3435 }
3436
3437 /// @brief updates a JSON object from another object, overwriting existing keys
3438 /// @sa https://json.nlohmann.me/api/basic_json/update/
3439 void update(const_reference j, bool merge_objects = false)
3440 {
3441 update(j.begin(), j.end(), merge_objects);
3442 }
3443
3444 /// @brief updates a JSON object from another object, overwriting existing keys
3445 /// @sa https://json.nlohmann.me/api/basic_json/update/
3446 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
3447 {
3448 // implicitly convert a null value to an empty object
3449 if (is_null())
3450 {
3451 m_data.m_type = value_t::object;
3452 m_data.m_value.object = create<object_t>();
3453 assert_invariant();
3454 }
3455
3456 if (JSON_HEDLEY_UNLIKELY(!is_object()))
3457 {
3458 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
3459 }
3460
3461 // check if range iterators belong to the same JSON object
3462 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3463 {
3464 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3465 }
3466
3467 // passed iterators must belong to objects
3468 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3469 {
3470 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
3471 }
3472
3473 for (auto it = first; it != last; ++it)
3474 {
3475 if (merge_objects && it.value().is_object())
3476 {
3477 auto it2 = m_data.m_value.object->find(it.key());
3478 if (it2 != m_data.m_value.object->end())
3479 {
3480 it2->second.update(it.value(), true);
3481 continue;
3482 }
3483 }
3484 m_data.m_value.object->operator[](it.key()) = it.value();
3485#if JSON_DIAGNOSTICS
3486 m_data.m_value.object->operator[](it.key()).m_parent = this;
3487#endif
3488 }
3489 }
3490
3491 /// @brief exchanges the values
3492 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3493 void swap(reference other) noexcept (
3494 std::is_nothrow_move_constructible<value_t>::value&&
3495 std::is_nothrow_move_assignable<value_t>::value&&
3496 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3497 std::is_nothrow_move_assignable<json_value>::value
3498 )
3499 {
3500 std::swap(m_data.m_type, other.m_data.m_type);
3501 std::swap(m_data.m_value, other.m_data.m_value);
3502
3503 set_parents();
3504 other.set_parents();
3505 assert_invariant();
3506 }
3507
3508 /// @brief exchanges the values
3509 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3510 friend void swap(reference left, reference right) noexcept (
3511 std::is_nothrow_move_constructible<value_t>::value&&
3512 std::is_nothrow_move_assignable<value_t>::value&&
3513 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3514 std::is_nothrow_move_assignable<json_value>::value
3515 )
3516 {
3517 left.swap(right);
3518 }
3519
3520 /// @brief exchanges the values
3521 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3522 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3523 {
3524 // swap only works for arrays
3525 if (JSON_HEDLEY_LIKELY(is_array()))
3526 {
3527 using std::swap;
3528 swap(*(m_data.m_value.array), other);
3529 }
3530 else
3531 {
3532 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
3533 }
3534 }
3535
3536 /// @brief exchanges the values
3537 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3538 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3539 {
3540 // swap only works for objects
3541 if (JSON_HEDLEY_LIKELY(is_object()))
3542 {
3543 using std::swap;
3544 swap(*(m_data.m_value.object), other);
3545 }
3546 else
3547 {
3548 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
3549 }
3550 }
3551
3552 /// @brief exchanges the values
3553 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3554 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3555 {
3556 // swap only works for strings
3557 if (JSON_HEDLEY_LIKELY(is_string()))
3558 {
3559 using std::swap;
3560 swap(*(m_data.m_value.string), other);
3561 }
3562 else
3563 {
3564 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
3565 }
3566 }
3567
3568 /// @brief exchanges the values
3569 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3570 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3571 {
3572 // swap only works for strings
3573 if (JSON_HEDLEY_LIKELY(is_binary()))
3574 {
3575 using std::swap;
3576 swap(*(m_data.m_value.binary), other);
3577 }
3578 else
3579 {
3580 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
3581 }
3582 }
3583
3584 /// @brief exchanges the values
3585 /// @sa https://json.nlohmann.me/api/basic_json/swap/
3586 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
3587 {
3588 // swap only works for strings
3589 if (JSON_HEDLEY_LIKELY(is_binary()))
3590 {
3591 using std::swap;
3592 swap(*(m_data.m_value.binary), other);
3593 }
3594 else
3595 {
3596 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
3597 }
3598 }
3599
3600 /// @}
3601
3602 //////////////////////////////////////////
3603 // lexicographical comparison operators //
3604 //////////////////////////////////////////
3605
3606 /// @name lexicographical comparison operators
3607 /// @{
3608
3609 // note parentheses around operands are necessary; see
3610 // https://github.com/nlohmann/json/issues/1530
3611#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
3612 const auto lhs_type = lhs.type(); \
3613 const auto rhs_type = rhs.type(); \
3614 \
3615 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
3616 { \
3617 switch (lhs_type) \
3618 { \
3619 case value_t::array: \
3620 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
3621 \
3622 case value_t::object: \
3623 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
3624 \
3625 case value_t::null: \
3626 return (null_result); \
3627 \
3628 case value_t::string: \
3629 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
3630 \
3631 case value_t::boolean: \
3632 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
3633 \
3634 case value_t::number_integer: \
3635 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
3636 \
3637 case value_t::number_unsigned: \
3638 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
3639 \
3640 case value_t::number_float: \
3641 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
3642 \
3643 case value_t::binary: \
3644 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
3645 \
3646 case value_t::discarded: \
3647 default: \
3648 return (unordered_result); \
3649 } \
3650 } \
3651 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
3652 { \
3653 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
3654 } \
3655 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
3656 { \
3657 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
3658 } \
3659 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
3660 { \
3661 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
3662 } \
3663 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
3664 { \
3665 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
3666 } \
3667 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
3668 { \
3669 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
3670 } \
3671 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
3672 { \
3673 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
3674 } \
3675 else if(compares_unordered(lhs, rhs))\
3676 {\
3677 return (unordered_result);\
3678 }\
3679 \
3680 return (default_result);
3681
3682 JSON_PRIVATE_UNLESS_TESTED:
3683 // returns true if:
3684 // - any operand is NaN and the other operand is of number type
3685 // - any operand is discarded
3686 // in legacy mode, discarded values are considered ordered if
3687 // an operation is computed as an odd number of inverses of others
3688 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
3689 {
3690 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
3691 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
3692 {
3693 return true;
3694 }
3695#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3696 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
3697#else
3698 static_cast<void>(inverse);
3699 return lhs.is_discarded() || rhs.is_discarded();
3700#endif
3701 }
3702
3703 private:
3704 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
3705 {
3706 return compares_unordered(*this, rhs, inverse);
3707 }
3708
3709 public:
3710#if JSON_HAS_THREE_WAY_COMPARISON
3711 /// @brief comparison: equal
3712 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3713 bool operator==(const_reference rhs) const noexcept
3714 {
3715#ifdef __GNUC__
3716#pragma GCC diagnostic push
3717#pragma GCC diagnostic ignored "-Wfloat-equal"
3718#endif
3719 const_reference lhs = *this;
3720 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3721#ifdef __GNUC__
3722#pragma GCC diagnostic pop
3723#endif
3724 }
3725
3726 /// @brief comparison: equal
3727 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3728 template<typename ScalarType>
3729 requires std::is_scalar_v<ScalarType>
3730 bool operator==(ScalarType rhs) const noexcept
3731 {
3732 return *this == basic_json(rhs);
3733 }
3734
3735 /// @brief comparison: not equal
3736 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3737 bool operator!=(const_reference rhs) const noexcept
3738 {
3739 if (compares_unordered(rhs, true))
3740 {
3741 return false;
3742 }
3743 return !operator==(rhs);
3744 }
3745
3746 /// @brief comparison: 3-way
3747 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3748 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
3749 {
3750 const_reference lhs = *this;
3751 // default_result is used if we cannot compare values. In that case,
3752 // we compare types.
3753 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
3754 std::partial_ordering::equivalent,
3755 std::partial_ordering::unordered,
3756 lhs_type <=> rhs_type) // *NOPAD*
3757 }
3758
3759 /// @brief comparison: 3-way
3760 /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3761 template<typename ScalarType>
3762 requires std::is_scalar_v<ScalarType>
3763 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
3764 {
3765 return *this <=> basic_json(rhs); // *NOPAD*
3766 }
3767
3768#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3769 // all operators that are computed as an odd number of inverses of others
3770 // need to be overloaded to emulate the legacy comparison behavior
3771
3772 /// @brief comparison: less than or equal
3773 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3774 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3775 bool operator<=(const_reference rhs) const noexcept
3776 {
3777 if (compares_unordered(rhs, true))
3778 {
3779 return false;
3780 }
3781 return !(rhs < *this);
3782 }
3783
3784 /// @brief comparison: less than or equal
3785 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3786 template<typename ScalarType>
3787 requires std::is_scalar_v<ScalarType>
3788 bool operator<=(ScalarType rhs) const noexcept
3789 {
3790 return *this <= basic_json(rhs);
3791 }
3792
3793 /// @brief comparison: greater than or equal
3794 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3795 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3796 bool operator>=(const_reference rhs) const noexcept
3797 {
3798 if (compares_unordered(rhs, true))
3799 {
3800 return false;
3801 }
3802 return !(*this < rhs);
3803 }
3804
3805 /// @brief comparison: greater than or equal
3806 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3807 template<typename ScalarType>
3808 requires std::is_scalar_v<ScalarType>
3809 bool operator>=(ScalarType rhs) const noexcept
3810 {
3811 return *this >= basic_json(rhs);
3812 }
3813#endif
3814#else
3815 /// @brief comparison: equal
3816 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3817 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
3818 {
3819#ifdef __GNUC__
3820#pragma GCC diagnostic push
3821#pragma GCC diagnostic ignored "-Wfloat-equal"
3822#endif
3823 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3824#ifdef __GNUC__
3825#pragma GCC diagnostic pop
3826#endif
3827 }
3828
3829 /// @brief comparison: equal
3830 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3831 template<typename ScalarType, typename std::enable_if<
3832 std::is_scalar<ScalarType>::value, int>::type = 0>
3833 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
3834 {
3835 return lhs == basic_json(rhs);
3836 }
3837
3838 /// @brief comparison: equal
3839 /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3840 template<typename ScalarType, typename std::enable_if<
3841 std::is_scalar<ScalarType>::value, int>::type = 0>
3842 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
3843 {
3844 return basic_json(lhs) == rhs;
3845 }
3846
3847 /// @brief comparison: not equal
3848 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3849 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
3850 {
3851 if (compares_unordered(lhs, rhs, true))
3852 {
3853 return false;
3854 }
3855 return !(lhs == rhs);
3856 }
3857
3858 /// @brief comparison: not equal
3859 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3860 template<typename ScalarType, typename std::enable_if<
3861 std::is_scalar<ScalarType>::value, int>::type = 0>
3862 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
3863 {
3864 return lhs != basic_json(rhs);
3865 }
3866
3867 /// @brief comparison: not equal
3868 /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3869 template<typename ScalarType, typename std::enable_if<
3870 std::is_scalar<ScalarType>::value, int>::type = 0>
3871 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
3872 {
3873 return basic_json(lhs) != rhs;
3874 }
3875
3876 /// @brief comparison: less than
3877 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3878 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
3879 {
3880 // default_result is used if we cannot compare values. In that case,
3881 // we compare types. Note we have to call the operator explicitly,
3882 // because MSVC has problems otherwise.
3883 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
3884 }
3885
3886 /// @brief comparison: less than
3887 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3888 template<typename ScalarType, typename std::enable_if<
3889 std::is_scalar<ScalarType>::value, int>::type = 0>
3890 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
3891 {
3892 return lhs < basic_json(rhs);
3893 }
3894
3895 /// @brief comparison: less than
3896 /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3897 template<typename ScalarType, typename std::enable_if<
3898 std::is_scalar<ScalarType>::value, int>::type = 0>
3899 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
3900 {
3901 return basic_json(lhs) < rhs;
3902 }
3903
3904 /// @brief comparison: less than or equal
3905 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3906 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
3907 {
3908 if (compares_unordered(lhs, rhs, true))
3909 {
3910 return false;
3911 }
3912 return !(rhs < lhs);
3913 }
3914
3915 /// @brief comparison: less than or equal
3916 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3917 template<typename ScalarType, typename std::enable_if<
3918 std::is_scalar<ScalarType>::value, int>::type = 0>
3919 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
3920 {
3921 return lhs <= basic_json(rhs);
3922 }
3923
3924 /// @brief comparison: less than or equal
3925 /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3926 template<typename ScalarType, typename std::enable_if<
3927 std::is_scalar<ScalarType>::value, int>::type = 0>
3928 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
3929 {
3930 return basic_json(lhs) <= rhs;
3931 }
3932
3933 /// @brief comparison: greater than
3934 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3935 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
3936 {
3937 // double inverse
3938 if (compares_unordered(lhs, rhs))
3939 {
3940 return false;
3941 }
3942 return !(lhs <= rhs);
3943 }
3944
3945 /// @brief comparison: greater than
3946 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3947 template<typename ScalarType, typename std::enable_if<
3948 std::is_scalar<ScalarType>::value, int>::type = 0>
3949 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
3950 {
3951 return lhs > basic_json(rhs);
3952 }
3953
3954 /// @brief comparison: greater than
3955 /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3956 template<typename ScalarType, typename std::enable_if<
3957 std::is_scalar<ScalarType>::value, int>::type = 0>
3958 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
3959 {
3960 return basic_json(lhs) > rhs;
3961 }
3962
3963 /// @brief comparison: greater than or equal
3964 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3965 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
3966 {
3967 if (compares_unordered(lhs, rhs, true))
3968 {
3969 return false;
3970 }
3971 return !(lhs < rhs);
3972 }
3973
3974 /// @brief comparison: greater than or equal
3975 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3976 template<typename ScalarType, typename std::enable_if<
3977 std::is_scalar<ScalarType>::value, int>::type = 0>
3978 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
3979 {
3980 return lhs >= basic_json(rhs);
3981 }
3982
3983 /// @brief comparison: greater than or equal
3984 /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3985 template<typename ScalarType, typename std::enable_if<
3986 std::is_scalar<ScalarType>::value, int>::type = 0>
3987 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
3988 {
3989 return basic_json(lhs) >= rhs;
3990 }
3991#endif
3992
3993#undef JSON_IMPLEMENT_OPERATOR
3994
3995 /// @}
3996
3997 ///////////////////
3998 // serialization //
3999 ///////////////////
4000
4001 /// @name serialization
4002 /// @{
4003#ifndef JSON_NO_IO
4004 /// @brief serialize to stream
4005 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
4006 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
4007 {
4008 // read width member and use it as the indentation parameter if nonzero
4009 const bool pretty_print = o.width() > 0;
4010 const auto indentation = pretty_print ? o.width() : 0;
4011
4012 // reset width to 0 for subsequent calls to this stream
4013 o.width(0);
4014
4015 // do the actual serialization
4016 serializer s(detail::output_adapter<char>(o), o.fill());
4017 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
4018 return o;
4019 }
4020
4021 /// @brief serialize to stream
4022 /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
4023 /// @deprecated This function is deprecated since 3.0.0 and will be removed in
4024 /// version 4.0.0 of the library. Please use
4025 /// operator<<(std::ostream&, const basic_json&) instead; that is,
4026 /// replace calls like `j >> o;` with `o << j;`.
4027 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
4028 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
4029 {
4030 return o << j;
4031 }
4032#endif // JSON_NO_IO
4033 /// @}
4034
4035 /////////////////////
4036 // deserialization //
4037 /////////////////////
4038
4039 /// @name deserialization
4040 /// @{
4041
4042 /// @brief deserialize from a compatible input
4043 /// @sa https://json.nlohmann.me/api/basic_json/parse/
4044 template<typename InputType>
4045 JSON_HEDLEY_WARN_UNUSED_RESULT
4046 static basic_json parse(InputType&& i,
4047 parser_callback_t cb = nullptr,
4048 const bool allow_exceptions = true,
4049 const bool ignore_comments = false,
4050 const bool ignore_trailing_commas = false)
4051 {
4052 basic_json result;
4053 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
4054 return result;
4055 }
4056
4057 /// @brief deserialize from a pair of character iterators
4058 /// @sa https://json.nlohmann.me/api/basic_json/parse/
4059 template<typename IteratorType>
4060 JSON_HEDLEY_WARN_UNUSED_RESULT
4061 static basic_json parse(IteratorType first,
4062 IteratorType last,
4063 parser_callback_t cb = nullptr,
4064 const bool allow_exceptions = true,
4065 const bool ignore_comments = false,
4066 const bool ignore_trailing_commas = false)
4067 {
4068 basic_json result;
4069 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
4070 return result;
4071 }
4072
4073 JSON_HEDLEY_WARN_UNUSED_RESULT
4074 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
4075 static basic_json parse(detail::span_input_adapter&& i,
4076 parser_callback_t cb = nullptr,
4077 const bool allow_exceptions = true,
4078 const bool ignore_comments = false,
4079 const bool ignore_trailing_commas = false)
4080 {
4081 basic_json result;
4082 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments, ignore_trailing_commas).parse(true, result); // cppcheck-suppress[accessMoved]
4083 return result;
4084 }
4085
4086 /// @brief check if the input is valid JSON
4087 /// @sa https://json.nlohmann.me/api/basic_json/accept/
4088 template<typename InputType>
4089 static bool accept(InputType&& i,
4090 const bool ignore_comments = false,
4091 const bool ignore_trailing_commas = false)
4092 {
4093 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
4094 }
4095
4096 /// @brief check if the input is valid JSON
4097 /// @sa https://json.nlohmann.me/api/basic_json/accept/
4098 template<typename IteratorType>
4099 static bool accept(IteratorType first, IteratorType last,
4100 const bool ignore_comments = false,
4101 const bool ignore_trailing_commas = false)
4102 {
4103 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
4104 }
4105
4106 JSON_HEDLEY_WARN_UNUSED_RESULT
4107 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
4108 static bool accept(detail::span_input_adapter&& i,
4109 const bool ignore_comments = false,
4110 const bool ignore_trailing_commas = false)
4111 {
4112 return parser(i.get(), nullptr, false, ignore_comments, ignore_trailing_commas).accept(true);
4113 }
4114
4115 /// @brief generate SAX events
4116 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4117 template <typename InputType, typename SAX>
4118 JSON_HEDLEY_NON_NULL(2)
4119 static bool sax_parse(InputType&& i, SAX* sax,
4120 input_format_t format = input_format_t::json,
4121 const bool strict = true,
4122 const bool ignore_comments = false,
4123 const bool ignore_trailing_commas = false)
4124 {
4125#if defined(__clang__)
4126#pragma clang diagnostic push
4127#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
4128#elif defined(__GNUC__)
4129#pragma GCC diagnostic push
4130#pragma GCC diagnostic ignored "-Wnonnull-compare"
4131#endif
4132 if (sax == nullptr)
4133 {
4134 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
4135 }
4136#if defined(__clang__)
4137#pragma clang diagnostic pop
4138#elif defined(__GNUC__)
4139#pragma GCC diagnostic pop
4140#endif
4141 auto ia = detail::input_adapter(std::forward<InputType>(i));
4142 return format == input_format_t::json
4143 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
4144 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4145 }
4146
4147 /// @brief generate SAX events
4148 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4149 template<class IteratorType, class SAX>
4150 JSON_HEDLEY_NON_NULL(3)
4151 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
4152 input_format_t format = input_format_t::json,
4153 const bool strict = true,
4154 const bool ignore_comments = false,
4155 const bool ignore_trailing_commas = false)
4156 {
4157#if defined(__clang__)
4158#pragma clang diagnostic push
4159#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
4160#elif defined(__GNUC__)
4161#pragma GCC diagnostic push
4162#pragma GCC diagnostic ignored "-Wnonnull-compare"
4163#endif
4164 if (sax == nullptr)
4165 {
4166 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
4167 }
4168#if defined(__clang__)
4169#pragma clang diagnostic pop
4170#elif defined(__GNUC__)
4171#pragma GCC diagnostic pop
4172#endif
4173 auto ia = detail::input_adapter(std::move(first), std::move(last));
4174 return format == input_format_t::json
4175 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
4176 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4177 }
4178
4179 /// @brief generate SAX events
4180 /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4181 /// @deprecated This function is deprecated since 3.8.0 and will be removed in
4182 /// version 4.0.0 of the library. Please use
4183 /// sax_parse(ptr, ptr + len) instead.
4184 template <typename SAX>
4185 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
4186 JSON_HEDLEY_NON_NULL(2)
4187 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
4188 input_format_t format = input_format_t::json,
4189 const bool strict = true,
4190 const bool ignore_comments = false,
4191 const bool ignore_trailing_commas = false)
4192 {
4193#if defined(__clang__)
4194#pragma clang diagnostic push
4195#pragma clang diagnostic ignored "-Wtautological-pointer-compare"
4196#elif defined(__GNUC__)
4197#pragma GCC diagnostic push
4198#pragma GCC diagnostic ignored "-Wnonnull-compare"
4199#endif
4200 if (sax == nullptr)
4201 {
4202 JSON_THROW(other_error::create(502, "SAX handler must not be null", nullptr));
4203 }
4204#if defined(__clang__)
4205#pragma clang diagnostic pop
4206#elif defined(__GNUC__)
4207#pragma GCC diagnostic pop
4208#endif
4209 auto ia = i.get();
4210 return format == input_format_t::json
4211 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4212 ? parser(std::move(ia), nullptr, true, ignore_comments, ignore_trailing_commas).sax_parse(sax, strict)
4213 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4214 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4215 }
4216#ifndef JSON_NO_IO
4217 /// @brief deserialize from stream
4218 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4219 /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
4220 /// version 4.0.0 of the library. Please use
4221 /// operator>>(std::istream&, basic_json&) instead; that is,
4222 /// replace calls like `j << i;` with `i >> j;`.
4223 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
4224 friend std::istream& operator<<(basic_json& j, std::istream& i)
4225 {
4226 return operator>>(i, j);
4227 }
4228
4229 /// @brief deserialize from stream
4230 /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4231 friend std::istream& operator>>(std::istream& i, basic_json& j)
4232 {
4233 parser(detail::input_adapter(i)).parse(false, j);
4234 return i;
4235 }
4236#endif // JSON_NO_IO
4237 /// @}
4238
4239 ///////////////////////////
4240 // convenience functions //
4241 ///////////////////////////
4242
4243 /// @brief return the type as string
4244 /// @sa https://json.nlohmann.me/api/basic_json/type_name/
4245 JSON_HEDLEY_RETURNS_NON_NULL
4246 const char* type_name() const noexcept
4247 {
4248 switch (m_data.m_type)
4249 {
4250 case value_t::null:
4251 return "null";
4252 case value_t::object:
4253 return "object";
4254 case value_t::array:
4255 return "array";
4256 case value_t::string:
4257 return "string";
4258 case value_t::boolean:
4259 return "boolean";
4260 case value_t::binary:
4261 return "binary";
4262 case value_t::discarded:
4263 return "discarded";
4264 case value_t::number_integer:
4265 case value_t::number_unsigned:
4266 case value_t::number_float:
4267 return "number";
4268 default:
4269 return "invalid";
4270 }
4271 }
4272
4273 JSON_PRIVATE_UNLESS_TESTED:
4274 //////////////////////
4275 // member variables //
4276 //////////////////////
4277
4278 struct data
4279 {
4280 /// the type of the current element
4281 value_t m_type = value_t::null;
4282
4283 /// the value of the current element
4284 json_value m_value = {};
4285
4286 data(const value_t v)
4287 : m_type(v), m_value(v)
4288 {
4289 }
4290
4291 data(size_type cnt, const basic_json& val)
4292 : m_type(value_t::array)
4293 {
4294 m_value.array = create<array_t>(cnt, val);
4295 }
4296
4297 data() noexcept = default;
4298 data(data&&) noexcept = default;
4299 data(const data&) noexcept = delete;
4300 data& operator=(data&&) noexcept = delete;
4301 data& operator=(const data&) noexcept = delete;
4302
4303 ~data() noexcept
4304 {
4305 m_value.destroy(m_type);
4306 }
4307 };
4308
4309 data m_data = {};
4310
4311#if JSON_DIAGNOSTICS
4312 /// a pointer to a parent value (for debugging purposes)
4313 basic_json* m_parent = nullptr;
4314#endif
4315
4316#if JSON_DIAGNOSTIC_POSITIONS
4317 /// the start position of the value
4318 std::size_t start_position = std::string::npos;
4319 /// the end position of the value
4320 std::size_t end_position = std::string::npos;
4321 public:
4322 constexpr std::size_t start_pos() const noexcept
4323 {
4324 return start_position;
4325 }
4326
4327 constexpr std::size_t end_pos() const noexcept
4328 {
4329 return end_position;
4330 }
4331#endif
4332
4333 //////////////////////////////////////////
4334 // binary serialization/deserialization //
4335 //////////////////////////////////////////
4336
4337 /// @name binary serialization/deserialization support
4338 /// @{
4339
4340 public:
4341 /// @brief create a CBOR serialization of a given JSON value
4342 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4343 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
4344 {
4345 std::vector<std::uint8_t> result;
4346 to_cbor(j, result);
4347 return result;
4348 }
4349
4350 /// @brief create a CBOR serialization of a given JSON value
4351 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4353 {
4354 binary_writer<std::uint8_t>(o).write_cbor(j);
4355 }
4356
4357 /// @brief create a CBOR serialization of a given JSON value
4358 /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4360 {
4361 binary_writer<char>(o).write_cbor(j);
4362 }
4363
4364 /// @brief create a MessagePack serialization of a given JSON value
4365 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4366 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
4367 {
4368 std::vector<std::uint8_t> result;
4369 to_msgpack(j, result);
4370 return result;
4371 }
4372
4373 /// @brief create a MessagePack serialization of a given JSON value
4374 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4376 {
4377 binary_writer<std::uint8_t>(o).write_msgpack(j);
4378 }
4379
4380 /// @brief create a MessagePack serialization of a given JSON value
4381 /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4383 {
4384 binary_writer<char>(o).write_msgpack(j);
4385 }
4386
4387 /// @brief create a UBJSON serialization of a given JSON value
4388 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4389 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
4390 const bool use_size = false,
4391 const bool use_type = false)
4392 {
4393 std::vector<std::uint8_t> result;
4394 to_ubjson(j, result, use_size, use_type);
4395 return result;
4396 }
4397
4398 /// @brief create a UBJSON serialization of a given JSON value
4399 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4401 const bool use_size = false, const bool use_type = false)
4402 {
4403 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
4404 }
4405
4406 /// @brief create a UBJSON serialization of a given JSON value
4407 /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4409 const bool use_size = false, const bool use_type = false)
4410 {
4411 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
4412 }
4413
4414 /// @brief create a BJData serialization of a given JSON value
4415 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4416 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
4417 const bool use_size = false,
4418 const bool use_type = false,
4419 const bjdata_version_t version = bjdata_version_t::draft2)
4420 {
4421 std::vector<std::uint8_t> result;
4422 to_bjdata(j, result, use_size, use_type, version);
4423 return result;
4424 }
4425
4426 /// @brief create a BJData serialization of a given JSON value
4427 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4429 const bool use_size = false, const bool use_type = false,
4430 const bjdata_version_t version = bjdata_version_t::draft2)
4431 {
4432 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
4433 }
4434
4435 /// @brief create a BJData serialization of a given JSON value
4436 /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4438 const bool use_size = false, const bool use_type = false,
4439 const bjdata_version_t version = bjdata_version_t::draft2)
4440 {
4441 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
4442 }
4443
4444 /// @brief create a BSON serialization of a given JSON value
4445 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4446 static std::vector<std::uint8_t> to_bson(const basic_json& j)
4447 {
4448 std::vector<std::uint8_t> result;
4449 to_bson(j, result);
4450 return result;
4451 }
4452
4453 /// @brief create a BSON serialization of a given JSON value
4454 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4456 {
4457 binary_writer<std::uint8_t>(o).write_bson(j);
4458 }
4459
4460 /// @brief create a BSON serialization of a given JSON value
4461 /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4463 {
4464 binary_writer<char>(o).write_bson(j);
4465 }
4466
4467 /// @brief create a JSON value from an input in CBOR format
4468 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4469 template<typename InputType>
4470 JSON_HEDLEY_WARN_UNUSED_RESULT
4471 static basic_json from_cbor(InputType&& i,
4472 const bool strict = true,
4473 const bool allow_exceptions = true,
4474 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4475 {
4476 basic_json result;
4477 auto ia = detail::input_adapter(std::forward<InputType>(i));
4478 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4479 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
4480 return res ? result : basic_json(value_t::discarded);
4481 }
4482
4483 /// @brief create a JSON value from an input in CBOR format
4484 /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4485 template<typename IteratorType>
4486 JSON_HEDLEY_WARN_UNUSED_RESULT
4487 static basic_json from_cbor(IteratorType first, IteratorType last,
4488 const bool strict = true,
4489 const bool allow_exceptions = true,
4490 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4491 {
4492 basic_json result;
4493 auto ia = detail::input_adapter(std::move(first), std::move(last));
4494 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4495 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
4496 return res ? result : basic_json(value_t::discarded);
4497 }
4498
4499 template<typename T>
4500 JSON_HEDLEY_WARN_UNUSED_RESULT
4501 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4502 static basic_json from_cbor(const T* ptr, std::size_t len,
4503 const bool strict = true,
4504 const bool allow_exceptions = true,
4505 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4506 {
4507 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
4508 }
4509
4510 JSON_HEDLEY_WARN_UNUSED_RESULT
4511 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4512 static basic_json from_cbor(detail::span_input_adapter&& i,
4513 const bool strict = true,
4514 const bool allow_exceptions = true,
4515 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4516 {
4517 basic_json result;
4518 auto ia = i.get();
4519 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4520 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4521 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
4522 return res ? result : basic_json(value_t::discarded);
4523 }
4524
4525 /// @brief create a JSON value from an input in MessagePack format
4526 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4527 template<typename InputType>
4528 JSON_HEDLEY_WARN_UNUSED_RESULT
4529 static basic_json from_msgpack(InputType&& i,
4530 const bool strict = true,
4531 const bool allow_exceptions = true)
4532 {
4533 basic_json result;
4534 auto ia = detail::input_adapter(std::forward<InputType>(i));
4535 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4536 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
4537 return res ? result : basic_json(value_t::discarded);
4538 }
4539
4540 /// @brief create a JSON value from an input in MessagePack format
4541 /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4542 template<typename IteratorType>
4543 JSON_HEDLEY_WARN_UNUSED_RESULT
4544 static basic_json from_msgpack(IteratorType first, IteratorType last,
4545 const bool strict = true,
4546 const bool allow_exceptions = true)
4547 {
4548 basic_json result;
4549 auto ia = detail::input_adapter(std::move(first), std::move(last));
4550 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4551 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
4552 return res ? result : basic_json(value_t::discarded);
4553 }
4554
4555 template<typename T>
4556 JSON_HEDLEY_WARN_UNUSED_RESULT
4557 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4558 static basic_json from_msgpack(const T* ptr, std::size_t len,
4559 const bool strict = true,
4560 const bool allow_exceptions = true)
4561 {
4562 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
4563 }
4564
4565 JSON_HEDLEY_WARN_UNUSED_RESULT
4566 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4567 static basic_json from_msgpack(detail::span_input_adapter&& i,
4568 const bool strict = true,
4569 const bool allow_exceptions = true)
4570 {
4571 basic_json result;
4572 auto ia = i.get();
4573 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4574 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4575 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
4576 return res ? result : basic_json(value_t::discarded);
4577 }
4578
4579 /// @brief create a JSON value from an input in UBJSON format
4580 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4581 template<typename InputType>
4582 JSON_HEDLEY_WARN_UNUSED_RESULT
4583 static basic_json from_ubjson(InputType&& i,
4584 const bool strict = true,
4585 const bool allow_exceptions = true)
4586 {
4587 basic_json result;
4588 auto ia = detail::input_adapter(std::forward<InputType>(i));
4589 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4590 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
4591 return res ? result : basic_json(value_t::discarded);
4592 }
4593
4594 /// @brief create a JSON value from an input in UBJSON format
4595 /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4596 template<typename IteratorType>
4597 JSON_HEDLEY_WARN_UNUSED_RESULT
4598 static basic_json from_ubjson(IteratorType first, IteratorType last,
4599 const bool strict = true,
4600 const bool allow_exceptions = true)
4601 {
4602 basic_json result;
4603 auto ia = detail::input_adapter(std::move(first), std::move(last));
4604 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4605 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
4606 return res ? result : basic_json(value_t::discarded);
4607 }
4608
4609 template<typename T>
4610 JSON_HEDLEY_WARN_UNUSED_RESULT
4611 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4612 static basic_json from_ubjson(const T* ptr, std::size_t len,
4613 const bool strict = true,
4614 const bool allow_exceptions = true)
4615 {
4616 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
4617 }
4618
4619 JSON_HEDLEY_WARN_UNUSED_RESULT
4620 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4621 static basic_json from_ubjson(detail::span_input_adapter&& i,
4622 const bool strict = true,
4623 const bool allow_exceptions = true)
4624 {
4625 basic_json result;
4626 auto ia = i.get();
4627 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4628 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4629 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
4630 return res ? result : basic_json(value_t::discarded);
4631 }
4632
4633 /// @brief create a JSON value from an input in BJData format
4634 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4635 template<typename InputType>
4636 JSON_HEDLEY_WARN_UNUSED_RESULT
4637 static basic_json from_bjdata(InputType&& i,
4638 const bool strict = true,
4639 const bool allow_exceptions = true)
4640 {
4641 basic_json result;
4642 auto ia = detail::input_adapter(std::forward<InputType>(i));
4643 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4644 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
4645 return res ? result : basic_json(value_t::discarded);
4646 }
4647
4648 /// @brief create a JSON value from an input in BJData format
4649 /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4650 template<typename IteratorType>
4651 JSON_HEDLEY_WARN_UNUSED_RESULT
4652 static basic_json from_bjdata(IteratorType first, IteratorType last,
4653 const bool strict = true,
4654 const bool allow_exceptions = true)
4655 {
4656 basic_json result;
4657 auto ia = detail::input_adapter(std::move(first), std::move(last));
4658 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4659 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
4660 return res ? result : basic_json(value_t::discarded);
4661 }
4662
4663 /// @brief create a JSON value from an input in BSON format
4664 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4665 template<typename InputType>
4666 JSON_HEDLEY_WARN_UNUSED_RESULT
4667 static basic_json from_bson(InputType&& i,
4668 const bool strict = true,
4669 const bool allow_exceptions = true)
4670 {
4671 basic_json result;
4672 auto ia = detail::input_adapter(std::forward<InputType>(i));
4673 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4674 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
4675 return res ? result : basic_json(value_t::discarded);
4676 }
4677
4678 /// @brief create a JSON value from an input in BSON format
4679 /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4680 template<typename IteratorType>
4681 JSON_HEDLEY_WARN_UNUSED_RESULT
4682 static basic_json from_bson(IteratorType first, IteratorType last,
4683 const bool strict = true,
4684 const bool allow_exceptions = true)
4685 {
4686 basic_json result;
4687 auto ia = detail::input_adapter(std::move(first), std::move(last));
4688 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4689 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
4690 return res ? result : basic_json(value_t::discarded);
4691 }
4692
4693 template<typename T>
4694 JSON_HEDLEY_WARN_UNUSED_RESULT
4695 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4696 static basic_json from_bson(const T* ptr, std::size_t len,
4697 const bool strict = true,
4698 const bool allow_exceptions = true)
4699 {
4700 return from_bson(ptr, ptr + len, strict, allow_exceptions);
4701 }
4702
4703 JSON_HEDLEY_WARN_UNUSED_RESULT
4704 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4705 static basic_json from_bson(detail::span_input_adapter&& i,
4706 const bool strict = true,
4707 const bool allow_exceptions = true)
4708 {
4709 basic_json result;
4710 auto ia = i.get();
4711 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
4712 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4713 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
4714 return res ? result : basic_json(value_t::discarded);
4715 }
4716 /// @}
4717
4718 //////////////////////////
4719 // JSON Pointer support //
4720 //////////////////////////
4721
4722 /// @name JSON Pointer functions
4723 /// @{
4724
4725 /// @brief access specified element via JSON Pointer
4726 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4727 reference operator[](const json_pointer& ptr)
4728 {
4729 return ptr.get_unchecked(this);
4730 }
4731
4732 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4733 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4734 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4735 {
4736 return ptr.get_unchecked(this);
4737 }
4738
4739 /// @brief access specified element via JSON Pointer
4740 /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4741 const_reference operator[](const json_pointer& ptr) const
4742 {
4743 return ptr.get_unchecked(this);
4744 }
4745
4746 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4747 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4748 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4749 {
4750 return ptr.get_unchecked(this);
4751 }
4752
4753 /// @brief access specified element via JSON Pointer
4754 /// @sa https://json.nlohmann.me/api/basic_json/at/
4755 reference at(const json_pointer& ptr)
4756 {
4757 return ptr.get_checked(this);
4758 }
4759
4760 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4761 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4762 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4763 {
4764 return ptr.get_checked(this);
4765 }
4766
4767 /// @brief access specified element via JSON Pointer
4768 /// @sa https://json.nlohmann.me/api/basic_json/at/
4769 const_reference at(const json_pointer& ptr) const
4770 {
4771 return ptr.get_checked(this);
4772 }
4773
4774 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4775 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4776 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4777 {
4778 return ptr.get_checked(this);
4779 }
4780
4781 /// @brief return flattened JSON value
4782 /// @sa https://json.nlohmann.me/api/basic_json/flatten/
4784 {
4785 basic_json result(value_t::object);
4786 json_pointer::flatten("", *this, result);
4787 return result;
4788 }
4789
4790 /// @brief unflatten a previously flattened JSON value
4791 /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
4793 {
4794 return json_pointer::unflatten(*this);
4795 }
4796
4797 /// @}
4798
4799 //////////////////////////
4800 // JSON Patch functions //
4801 //////////////////////////
4802
4803 /// @name JSON Patch functions
4804 /// @{
4805
4806 /// @brief applies a JSON patch in-place without copying the object
4807 /// @sa https://json.nlohmann.me/api/basic_json/patch/
4808 void patch_inplace(const basic_json& json_patch)
4809 {
4810 basic_json& result = *this;
4811 // the valid JSON Patch operations
4812 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
4813
4814 const auto get_op = [](const string_t& op)
4815 {
4816 if (op == "add")
4817 {
4818 return patch_operations::add;
4819 }
4820 if (op == "remove")
4821 {
4822 return patch_operations::remove;
4823 }
4824 if (op == "replace")
4825 {
4826 return patch_operations::replace;
4827 }
4828 if (op == "move")
4829 {
4830 return patch_operations::move;
4831 }
4832 if (op == "copy")
4833 {
4834 return patch_operations::copy;
4835 }
4836 if (op == "test")
4837 {
4838 return patch_operations::test;
4839 }
4840
4841 return patch_operations::invalid;
4842 };
4843
4844 // wrapper for "add" operation; add value at ptr
4845 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
4846 {
4847 // adding to the root of the target document means replacing it
4848 if (ptr.empty())
4849 {
4850 result = val;
4851 return;
4852 }
4853
4854 // make sure the top element of the pointer exists
4855 json_pointer const top_pointer = ptr.top();
4856 if (top_pointer != ptr)
4857 {
4858 result.at(top_pointer);
4859 }
4860
4861 // get reference to the parent of the JSON pointer ptr
4862 const auto last_path = ptr.back();
4863 ptr.pop_back();
4864 // parent must exist when performing patch add per RFC6902 specs
4865 basic_json& parent = result.at(ptr);
4866
4867 switch (parent.m_data.m_type)
4868 {
4869 case value_t::null:
4870 case value_t::object:
4871 {
4872 // use operator[] to add value
4873 parent[last_path] = val;
4874 break;
4875 }
4876
4877 case value_t::array:
4878 {
4879 if (last_path == "-")
4880 {
4881 // special case: append to back
4882 parent.push_back(val);
4883 }
4884 else
4885 {
4886 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
4887 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
4888 {
4889 // avoid undefined behavior
4890 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
4891 }
4892
4893 // default case: insert add offset
4894 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
4895 }
4896 break;
4897 }
4898
4899 // if there exists a parent, it cannot be primitive
4900 case value_t::string: // LCOV_EXCL_LINE
4901 case value_t::boolean: // LCOV_EXCL_LINE
4902 case value_t::number_integer: // LCOV_EXCL_LINE
4903 case value_t::number_unsigned: // LCOV_EXCL_LINE
4904 case value_t::number_float: // LCOV_EXCL_LINE
4905 case value_t::binary: // LCOV_EXCL_LINE
4906 case value_t::discarded: // LCOV_EXCL_LINE
4907 default: // LCOV_EXCL_LINE
4908 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
4909 }
4910 };
4911
4912 // wrapper for "remove" operation; remove value at ptr
4913 const auto operation_remove = [this, & result](json_pointer & ptr)
4914 {
4915 // get reference to the parent of the JSON pointer ptr
4916 const auto last_path = ptr.back();
4917 ptr.pop_back();
4918 basic_json& parent = result.at(ptr);
4919
4920 // remove child
4921 if (parent.is_object())
4922 {
4923 // perform range check
4924 auto it = parent.find(last_path);
4925 if (JSON_HEDLEY_LIKELY(it != parent.end()))
4926 {
4927 parent.erase(it);
4928 }
4929 else
4930 {
4931 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
4932 }
4933 }
4934 else if (parent.is_array())
4935 {
4936 // note erase performs range check
4937 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
4938 }
4939 };
4940
4941 // type check: top level value must be an array
4942 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
4943 {
4944 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
4945 }
4946
4947 // iterate and apply the operations
4948 for (const auto& val : json_patch)
4949 {
4950 // wrapper to get a value for an operation
4951 const auto get_value = [&val](const string_t& op,
4952 const string_t& member,
4953 bool string_type) -> basic_json &
4954 {
4955 // find value
4956 auto it = val.m_data.m_value.object->find(member);
4957
4958 // context-sensitive error message
4959 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
4960
4961 // check if the desired value is present
4962 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
4963 {
4964 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4965 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
4966 }
4967
4968 // check if the result is of type string
4969 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
4970 {
4971 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4972 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
4973 }
4974
4975 // no error: return value
4976 return it->second;
4977 };
4978
4979 // type check: every element of the array must be an object
4980 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
4981 {
4982 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
4983 }
4984
4985 // collect mandatory members
4986 const auto op = get_value("op", "op", true).template get<string_t>();
4987 const auto path = get_value(op, "path", true).template get<string_t>();
4988 json_pointer ptr(path);
4989
4990 switch (get_op(op))
4991 {
4992 case patch_operations::add:
4993 {
4994 operation_add(ptr, get_value("add", "value", false));
4995 break;
4996 }
4997
4998 case patch_operations::remove:
4999 {
5000 operation_remove(ptr);
5001 break;
5002 }
5003
5004 case patch_operations::replace:
5005 {
5006 // the "path" location must exist - use at()
5007 result.at(ptr) = get_value("replace", "value", false);
5008 break;
5009 }
5010
5011 case patch_operations::move:
5012 {
5013 const auto from_path = get_value("move", "from", true).template get<string_t>();
5014 json_pointer from_ptr(from_path);
5015
5016 // the "from" location must exist - use at()
5017 basic_json const v = result.at(from_ptr);
5018
5019 // The move operation is functionally identical to a
5020 // "remove" operation on the "from" location, followed
5021 // immediately by an "add" operation at the target
5022 // location with the value that was just removed.
5023 operation_remove(from_ptr);
5024 operation_add(ptr, v);
5025 break;
5026 }
5027
5028 case patch_operations::copy:
5029 {
5030 const auto from_path = get_value("copy", "from", true).template get<string_t>();
5031 const json_pointer from_ptr(from_path);
5032
5033 // the "from" location must exist - use at()
5034 basic_json const v = result.at(from_ptr);
5035
5036 // The copy is functionally identical to an "add"
5037 // operation at the target location using the value
5038 // specified in the "from" member.
5039 operation_add(ptr, v);
5040 break;
5041 }
5042
5043 case patch_operations::test:
5044 {
5045 bool success = false;
5046 JSON_TRY
5047 {
5048 // check if "value" matches the one at "path"
5049 // the "path" location must exist - use at()
5050 success = (result.at(ptr) == get_value("test", "value", false));
5051 }
5052 JSON_INTERNAL_CATCH (out_of_range&)
5053 {
5054 // ignore out of range errors: success remains false
5055 }
5056
5057 // throw an exception if the test fails
5058 if (JSON_HEDLEY_UNLIKELY(!success))
5059 {
5060 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
5061 }
5062
5063 break;
5064 }
5065
5066 case patch_operations::invalid:
5067 default:
5068 {
5069 // op must be "add", "remove", "replace", "move", "copy", or
5070 // "test"
5071 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
5072 }
5073 }
5074 }
5075 }
5076
5077 /// @brief applies a JSON patch to a copy of the current object
5078 /// @sa https://json.nlohmann.me/api/basic_json/patch/
5079 basic_json patch(const basic_json& json_patch) const
5080 {
5081 basic_json result = *this;
5082 result.patch_inplace(json_patch);
5083 return result;
5084 }
5085
5086 /// @brief creates a diff as a JSON patch
5087 /// @sa https://json.nlohmann.me/api/basic_json/diff/
5088 JSON_HEDLEY_WARN_UNUSED_RESULT
5089 static basic_json diff(const basic_json& source, const basic_json& target,
5090 const string_t& path = "")
5091 {
5092 // the patch
5093 basic_json result(value_t::array);
5094
5095 // if the values are the same, return an empty patch
5096 if (source == target)
5097 {
5098 return result;
5099 }
5100
5101 if (source.type() != target.type())
5102 {
5103 // different types: replace value
5104 result.push_back(
5105 {
5106 {"op", "replace"}, {"path", path}, {"value", target}
5107 });
5108 return result;
5109 }
5110
5111 switch (source.type())
5112 {
5113 case value_t::array:
5114 {
5115 // first pass: traverse common elements
5116 std::size_t i = 0;
5117 while (i < source.size() && i < target.size())
5118 {
5119 // recursive call to compare array values at index i
5120 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
5121 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
5122 ++i;
5123 }
5124
5125 // We now reached the end of at least one array
5126 // in a second pass, traverse the remaining elements
5127
5128 // remove my remaining elements
5129 const auto end_index = static_cast<difference_type>(result.size());
5130 while (i < source.size())
5131 {
5132 // add operations in reverse order to avoid invalid
5133 // indices
5134 result.insert(result.begin() + end_index, object(
5135 {
5136 {"op", "remove"},
5137 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
5138 }));
5139 ++i;
5140 }
5141
5142 // add other remaining elements
5143 while (i < target.size())
5144 {
5145 result.push_back(
5146 {
5147 {"op", "add"},
5148 {"path", detail::concat<string_t>(path, "/-")},
5149 {"value", target[i]}
5150 });
5151 ++i;
5152 }
5153
5154 break;
5155 }
5156
5157 case value_t::object:
5158 {
5159 // first pass: traverse this object's elements
5160 for (auto it = source.cbegin(); it != source.cend(); ++it)
5161 {
5162 // escape the key name to be used in a JSON patch
5163 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
5164
5165 if (target.find(it.key()) != target.end())
5166 {
5167 // recursive call to compare object values at key it
5168 auto temp_diff = diff(it.value(), target[it.key()], path_key);
5169 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
5170 }
5171 else
5172 {
5173 // found a key that is not in o -> remove it
5174 result.push_back(object(
5175 {
5176 {"op", "remove"}, {"path", path_key}
5177 }));
5178 }
5179 }
5180
5181 // second pass: traverse other object's elements
5182 for (auto it = target.cbegin(); it != target.cend(); ++it)
5183 {
5184 if (source.find(it.key()) == source.end())
5185 {
5186 // found a key that is not in this -> add it
5187 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
5188 result.push_back(
5189 {
5190 {"op", "add"}, {"path", path_key},
5191 {"value", it.value()}
5192 });
5193 }
5194 }
5195
5196 break;
5197 }
5198
5199 case value_t::null:
5200 case value_t::string:
5201 case value_t::boolean:
5202 case value_t::number_integer:
5203 case value_t::number_unsigned:
5204 case value_t::number_float:
5205 case value_t::binary:
5206 case value_t::discarded:
5207 default:
5208 {
5209 // both primitive types: replace value
5210 result.push_back(
5211 {
5212 {"op", "replace"}, {"path", path}, {"value", target}
5213 });
5214 break;
5215 }
5216 }
5217
5218 return result;
5219 }
5220 /// @}
5221
5222 ////////////////////////////////
5223 // JSON Merge Patch functions //
5224 ////////////////////////////////
5225
5226 /// @name JSON Merge Patch functions
5227 /// @{
5228
5229 /// @brief applies a JSON Merge Patch
5230 /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
5231 void merge_patch(const basic_json& apply_patch)
5232 {
5233 if (apply_patch.is_object())
5234 {
5235 if (!is_object())
5236 {
5237 *this = object();
5238 }
5239 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
5240 {
5241 if (it.value().is_null())
5242 {
5243 erase(it.key());
5244 }
5245 else
5246 {
5247 operator[](it.key()).merge_patch(it.value());
5248 }
5249 }
5250 }
5251 else
5252 {
5253 *this = apply_patch;
5254 }
5255 }
5256
5257 /// @}
5258};
5259
5260/// @brief user-defined to_string function for JSON values
5261/// @sa https://json.nlohmann.me/api/basic_json/to_string/
5262NLOHMANN_BASIC_JSON_TPL_DECLARATION
5263std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
5264{
5265 return j.dump();
5266}
5267
5268inline namespace literals
5269{
5270inline namespace json_literals
5271{
5272
5273/// @brief user-defined string literal for JSON values
5274/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
5275JSON_HEDLEY_NON_NULL(1)
5276#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5277 inline nlohmann::json operator""_json(const char* s, std::size_t n)
5278#else
5279 // GCC 4.8 requires a space between "" and suffix
5280 inline nlohmann::json operator"" _json(const char* s, std::size_t n)
5281#endif
5282{
5283 return nlohmann::json::parse(s, s + n);
5284}
5285
5286#if defined(__cpp_char8_t)
5287JSON_HEDLEY_NON_NULL(1)
5288inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
5289{
5290 return nlohmann::json::parse(reinterpret_cast<const char*>(s),
5291 reinterpret_cast<const char*>(s) + n);
5292}
5293#endif
5294
5295/// @brief user-defined string literal for JSON pointer
5296/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
5297JSON_HEDLEY_NON_NULL(1)
5298#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5299 inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
5300#else
5301 // GCC 4.8 requires a space between "" and suffix
5302 inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
5303#endif
5304{
5305 return nlohmann::json::json_pointer(std::string(s, n));
5306}
5307
5308#if defined(__cpp_char8_t)
5309inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
5310{
5311 return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
5312}
5313#endif
5314
5315} // namespace json_literals
5316} // namespace literals
5317NLOHMANN_JSON_NAMESPACE_END
5318
5319///////////////////////
5320// nonmember support //
5321///////////////////////
5322
5323namespace std // NOLINT(cert-dcl58-cpp)
5324{
5325
5326/// @brief hash value for JSON objects
5327/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
5328NLOHMANN_BASIC_JSON_TPL_DECLARATION
5329struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
5330{
5331 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
5332 {
5333 return nlohmann::detail::hash(j);
5334 }
5335};
5336
5337// specialization for std::less<value_t>
5338template<>
5339struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
5340{
5341 /*!
5342 @brief compare two value_t enum values
5343 @since version 3.0.0
5344 */
5345 bool operator()(::nlohmann::detail::value_t lhs,
5346 ::nlohmann::detail::value_t rhs) const noexcept
5347 {
5348#if JSON_HAS_THREE_WAY_COMPARISON
5349 return std::is_lt(lhs <=> rhs); // *NOPAD*
5350#else
5351 return ::nlohmann::detail::operator<(lhs, rhs);
5352#endif
5353 }
5354};
5355
5356// C++20 prohibit function specialization in the std namespace.
5357#ifndef JSON_HAS_CPP_20
5358
5359/// @brief exchanges the values of two JSON objects
5360/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
5361NLOHMANN_BASIC_JSON_TPL_DECLARATION
5362inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
5363 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
5364 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
5365{
5366 j1.swap(j2);
5367}
5368
5369#endif
5370
5371} // namespace std
5372
5373#if JSON_USE_GLOBAL_UDLS
5374 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5375 using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5376 using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5377 #else
5378 // GCC 4.8 requires a space between "" and suffix
5379 using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5380 using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5381 #endif
5382#endif
5383
5384#include <nlohmann/detail/macro_unscope.hpp>
5385
5386#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
定义 json.hpp:100
static allocator_type get_allocator()
returns the allocator associated with the container
定义 json.hpp:244
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
定义 json.hpp:4359
void clear() noexcept
clears the contents
定义 json.hpp:3057
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:2332
basic_json & operator=(basic_json other) noexcept(//NOLINT(cppcoreguidelines-c-copy-assignment-signature, misc-unconventional-assign-operator)std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
定义 json.hpp:1253
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
定义 json.hpp:992
IteratorType erase(IteratorType pos)
remove element given an iterator
定义 json.hpp:2459
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
定义 json.hpp:369
size_type erase(KeyType &&key)
remove element from a JSON object given a key
定义 json.hpp:2645
size_type size() const noexcept
returns the number of elements
定义 json.hpp:2975
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
定义 json.hpp:4544
const_reference front() const
access the first element
定义 json.hpp:2431
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
定义 json.hpp:1041
reference operator+=(const basic_json &val)
add an object to an array
定义 json.hpp:3175
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
定义 json.hpp:2305
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
定义 json.hpp:1813
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
定义 json.hpp:853
ObjectType< StringType, basic_json, default_object_comparator_t, AllocatorType< std::pair< const StringType, basic_json > > > object_t
a type for an object
定义 json.hpp:337
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
定义 json.hpp:4808
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
定义 json.hpp:1371
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
定义 json.hpp:2012
const_iterator begin() const noexcept
returns an iterator to the first element
定义 json.hpp:2807
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
定义 json.hpp:2741
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
定义 json.hpp:227
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
定义 json.hpp:2169
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
定义 json.hpp:4462
iter_impl< basic_json > iterator
an iterator for a basic_json container
定义 json.hpp:232
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
定义 json.hpp:4667
constexpr bool is_array() const noexcept
定义 json.hpp:1392
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
定义 json.hpp:1826
iterator find(KeyType &&key)
find an element in a JSON object
定义 json.hpp:2711
void erase(const size_type idx)
remove element from a JSON array given an index
定义 json.hpp:2652
void push_back(const basic_json &val)
add an object to an array
定义 json.hpp:3151
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
定义 json.hpp:4529
basic_json(const value_t v)
create an empty value with a given type
定义 json.hpp:819
const_iterator find(KeyType &&key) const
find an element in a JSON object
定义 json.hpp:2727
binary_t & get_binary()
get a binary value
定义 json.hpp:1932
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
定义 json.hpp:3335
iterator find(const typename object_t::key_type &key)
定义 json.hpp:2681
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
定义 json.hpp:4741
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
定义 json.hpp:4637
reference at(size_type idx)
access specified array element with bounds checking
定义 json.hpp:1966
constexpr bool is_boolean() const noexcept
定义 json.hpp:1350
bool empty() const noexcept
checks whether the container is empty.
定义 json.hpp:2936
void swap(object_t &other)
exchanges the values
定义 json.hpp:3538
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
定义 json.hpp:236
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
定义 json.hpp:3510
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
定义 json.hpp:4682
NumberIntegerType number_integer_t
a type for a number (integer)
定义 json.hpp:357
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
定义 json.hpp:229
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
定义 json.hpp:981
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
定义 json.hpp:4755
reference emplace_back(Args &&... args)
add an object to an array
定义 json.hpp:3239
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
定义 json.hpp:2050
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
定义 json.hpp:2634
json_sax< basic_json > json_sax_t
SAX interface type, see nlohmann::json_sax
定义 json.hpp:182
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
定义 json.hpp:4652
constexpr bool is_null() const noexcept
定义 json.hpp:1343
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
定义 json.hpp:3413
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
定义 json.hpp:2775
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
定义 json.hpp:4487
const_iterator end() const noexcept
returns an iterator to one past the last element
定义 json.hpp:2832
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
定义 json.hpp:2695
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
定义 json.hpp:3446
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
定义 json.hpp:5079
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
定义 json.hpp:3315
const_reference back() const
access the last element
定义 json.hpp:2447
basic_json value_type
the type of elements in a basic_json container
定义 json.hpp:211
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
定义 json.hpp:4769
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
定义 json.hpp:4382
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
定义 json.hpp:3493
constexpr bool is_binary() const noexcept
定义 json.hpp:1406
reference operator[](size_type idx)
access specified array element
定义 json.hpp:2088
basic_json flatten() const
return flattened JSON value
定义 json.hpp:4783
reference front()
access the first element
定义 json.hpp:2424
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
定义 json.hpp:911
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const string_t &path="")
creates a diff as a JSON patch
定义 json.hpp:5089
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
定义 json.hpp:1022
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
定义 json.hpp:4598
iterator insert_iterator(const_iterator pos, Args &&... args)
定义 json.hpp:3296
value_type & reference
the type of an element reference
定义 json.hpp:214
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
定义 json.hpp:1584
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:2355
const_reference operator[](KeyType &&key) const
access specified object element
定义 json.hpp:2224
void swap(typename binary_t::container_type &other)
exchanges the values
定义 json.hpp:3586
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
定义 json.hpp:2381
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
定义 json.hpp:4471
reference operator+=(initializer_list_t init)
add an object to an object
定义 json.hpp:3230
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
定义 json.hpp:2751
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
定义 json.hpp:1772
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
定义 json.hpp:2768
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:4408
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
定义 json.hpp:238
constexpr bool is_number_integer() const noexcept
定义 json.hpp:1364
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
定义 json.hpp:1029
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
定义 json.hpp:827
const_reference operator[](size_type idx) const
access specified array element
定义 json.hpp:2134
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
定义 json.hpp:4246
constexpr bool is_number_float() const noexcept
定义 json.hpp:1378
void swap(binary_t &other)
exchanges the values
定义 json.hpp:3570
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
定义 json.hpp:345
basic_json unflatten() const
unflatten a previously flattened JSON value
定义 json.hpp:4792
BooleanType boolean_t
a type for a boolean
定义 json.hpp:353
reference operator[](typename object_t::key_type key)
access specified object element
定义 json.hpp:2147
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
定义 json.hpp:361
basic_json(basic_json &&other) noexcept
move constructor
定义 json.hpp:1227
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
定义 json.hpp:2759
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
定义 json.hpp:4446
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
定义 json.hpp:4352
iterator begin() noexcept
returns an iterator to the first element
定义 json.hpp:2798
const_iterator cend() const noexcept
定义 json.hpp:2839
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
定义 json.hpp:970
basic_json(const basic_json &other)
copy constructor
定义 json.hpp:1154
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
定义 json.hpp:1573
detail::parse_event_t parse_event_t
parser event types
定义 json.hpp:802
reference operator+=(basic_json &&val)
add an object to an array
定义 json.hpp:3143
constexpr bool is_discarded() const noexcept
return whether value is discarded
定义 json.hpp:1413
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
定义 json.hpp:252
NumberFloatType number_float_t
a type for a number (floating-point)
定义 json.hpp:365
void push_back(initializer_list_t init)
add an object to an object
定义 json.hpp:3214
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
定义 json.hpp:4375
const binary_t & get_binary() const
get a binary value
定义 json.hpp:1944
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
定义 json.hpp:2279
void swap(array_t &other)
exchanges the values
定义 json.hpp:3522
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer
定义 json.hpp:168
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
定义 json.hpp:1003
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
定义 json.hpp:234
void push_back(basic_json &&val)
add an object to an array
定义 json.hpp:3118
detail::error_handler_t error_handler_t
how to treat decoding errors
定义 json.hpp:172
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
定义 json.hpp:4428
const value_type & const_reference
the type of an element const reference
定义 json.hpp:216
reference operator[](KeyType &&key)
access specified object element
定义 json.hpp:2200
ReferenceType get_ref() const
get a reference value (implicit)
定义 json.hpp:1873
const_reference at(KeyType &&key) const
access specified object element with bounds checking
定义 json.hpp:2070
reference operator+=(const typename object_t::value_type &val)
add an object to an object
定义 json.hpp:3206
constexpr bool is_structured() const noexcept
return whether type is structured
定义 json.hpp:1336
const_reverse_iterator crbegin() const noexcept
定义 json.hpp:2876
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
定义 json.hpp:3264
const_iterator cbegin() const noexcept
定义 json.hpp:2814
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
定义 json.hpp:2913
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
定义 json.hpp:3393
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
定义 json.hpp:1300
size_type max_size() const noexcept
returns the maximum possible number of elements
定义 json.hpp:3014
AllocatorType< basic_json > allocator_type
the allocator type
定义 json.hpp:224
reference at(KeyType &&key)
access specified object element with bounds checking
定义 json.hpp:2032
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
定义 json.hpp:3362
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
定义 json.hpp:806
~basic_json() noexcept
destructor
定义 json.hpp:1282
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
定义 json.hpp:2869
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
定义 json.hpp:4366
constexpr bool is_number() const noexcept
定义 json.hpp:1357
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
定义 json.hpp:2848
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:4389
const_reverse_iterator crend() const noexcept
定义 json.hpp:2883
std::ptrdiff_t difference_type
a type to represent differences between iterators
定义 json.hpp:219
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
定义 json.hpp:4583
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
定义 json.hpp:4455
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
定义 json.hpp:373
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
定义 json.hpp:3342
ReferenceType get_ref()
定义 json.hpp:1862
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
定义 json.hpp:2862
constexpr bool is_object() const noexcept
定义 json.hpp:1385
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
定义 json.hpp:2920
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
定义 json.hpp:1014
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
定义 json.hpp:1322
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
定义 json.hpp:2254
constexpr bool is_string() const noexcept
定义 json.hpp:1399
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
定义 json.hpp:3439
constexpr bool is_primitive() const noexcept
return whether type is primitive
定义 json.hpp:1329
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
定义 json.hpp:2529
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
定义 json.hpp:4416
json_value m_value
the value of the current element
定义 json.hpp:4284
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
定义 json.hpp:2895
detail::cbor_tag_handler_t cbor_tag_handler_t
how to treat CBOR tags
定义 json.hpp:174
friend std::istream & operator>>(std::istream &i, basic_json &j)
定义 json.hpp:4231
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
定义 json.hpp:839
StringType string_t
a type for a string
定义 json.hpp:349
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
定义 json.hpp:178
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
定义 json.hpp:4343
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
定义 json.hpp:5231
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
定义 json.hpp:4727
detail::bjdata_version_t bjdata_version_t
how to encode BJData
定义 json.hpp:176
std::size_t size_type
a type to represent container sizes
定义 json.hpp:221
void push_back(const typename object_t::value_type &val)
add an object to an object
定义 json.hpp:3183
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
定义 json.hpp:4400
std::less< StringType > default_object_comparator_t
default object key comparator type The actual object key comparator type (object_comparator_t) may be...
定义 json.hpp:332
const_reference at(size_type idx) const
access specified array element with bounds checking
定义 json.hpp:1989
reference back()
access the last element
定义 json.hpp:2438
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
定义 json.hpp:4437
void swap(string_t &other)
exchanges the values
定义 json.hpp:3554
iterator end() noexcept
returns an iterator to one past the last element
定义 json.hpp:2823
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
定义 json.hpp:2855
deserialization of CBOR, MessagePack, and UBJSON values
定义 binary_reader.hpp:70
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
定义 binary_reader.hpp:107
general exception of the basic_json class
定义 exceptions.hpp:51
exception indicating errors with iterators
定义 exceptions.hpp:220
定义 json_ref.hpp:23
SAX implementation to create a JSON value from SAX events
定义 json_sax.hpp:168
exception indicating other library errors
定义 exceptions.hpp:272
exception indicating access out of the defined range
定义 exceptions.hpp:255
定义 output_adapters.hpp:123
exception indicating a parse error
定义 exceptions.hpp:167
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
定义 exceptions.hpp:179
定义 input_adapters.hpp:522
exception indicating executing a member function with a wrong type
定义 exceptions.hpp:238
void pop_back()
remove last reference token
定义 json_pointer.hpp:159
bool empty() const noexcept
return whether pointer points to the root document
定义 json_pointer.hpp:197
const string_t & back() const
return last reference token
定义 json_pointer.hpp:171
detail namespace with internal helper functions
定义 from_json.hpp:43
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
定义 string_escape.hpp:50
cbor_tag_handler_t
how to treat CBOR tags
定义 binary_reader.hpp:43
parse_event_t
定义 parser.hpp:35
error_handler_t
how to treat decoding errors
定义 serializer.hpp:44
value_t
the JSON type enumeration
定义 value_t.hpp:54
@ number_integer
number value (signed integer)
定义 value_t.hpp:60
@ binary
binary array (ordered collection of bytes)
定义 value_t.hpp:63
@ string
string value
定义 value_t.hpp:58
@ number_float
number value (floating-point)
定义 value_t.hpp:62
@ number_unsigned
number value (unsigned integer)
定义 value_t.hpp:61
@ array
array (ordered collection of values)
定义 value_t.hpp:57
input_format_t
the supported input formats
定义 input_adapters.hpp:37
bjdata_version_t
how to encode BJData
定义 binary_writer.hpp:33
定义 type_traits.hpp:273
定义 to_json.hpp:47
定义 type_traits.hpp:116
定义 type_traits.hpp:141
定义 type_traits.hpp:52
定义 type_traits.hpp:600
定义 type_traits.hpp:560
定义 type_traits.hpp:286
定义 detected.hpp:51
定义 type_traits.hpp:831
定义 type_traits.hpp:280
定义 cpp_future.hpp:149
SAX interface
定义 json_sax.hpp:33
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
定义 json.hpp:5345
vrpn_SendTextMessageStreamProxy operator<<(vrpn_BaseClassUnique::SendTextMessageBoundCall const &call, T const &firstData)
定义 vrpn_SendTextMessageStreamProxy.h:110