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