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