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