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