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

Provided by KDAB

Privacy Policy
Learn more about Flutter for embedded and desktop on industrialflutter.com

source code of flutter_engine/third_party/json/include/nlohmann/json.hpp