mirror of
https://github.com/nlohmann/json.git
synced 2026-09-30 03:30:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07fee4fd55 |
@@ -6,7 +6,9 @@ void swap(reference other) noexcept (
|
||||
std::is_nothrow_move_constructible<value_t>::value &&
|
||||
std::is_nothrow_move_assignable<value_t>::value &&
|
||||
std::is_nothrow_move_constructible<json_value>::value &&
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value &&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value &&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
);
|
||||
|
||||
// (2)
|
||||
@@ -14,7 +16,9 @@ friend void swap(reference left, reference right) noexcept (
|
||||
std::is_nothrow_move_constructible<value_t>::value &&
|
||||
std::is_nothrow_move_assignable<value_t>::value &&
|
||||
std::is_nothrow_move_constructible<json_value>::value &&
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value &&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value &&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
);
|
||||
|
||||
// (3)
|
||||
@@ -37,11 +41,15 @@ void swap(typename binary_t::container_type& other);
|
||||
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated. If macro
|
||||
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
||||
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
||||
The [`json_base_class_t`](json_base_class_t.md) subobject is exchanged along with the value as well, the same way it
|
||||
is copied or moved by the copy/move constructors and assignment operators.
|
||||
2. Exchanges the contents of the JSON value from `left` with those of `right`. Does not invoke any move, copy, or swap
|
||||
operations on individual elements. All iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated. Implemented as a friend function callable via ADL. If macro
|
||||
[`JSON_DIAGNOSTIC_POSITIONS`](../macros/json_diagnostic_positions.md) is defined to `#!cpp 1`, the
|
||||
[`start_pos()`](start_pos.md)/[`end_pos()`](end_pos.md) diagnostic positions are exchanged along with the value.
|
||||
The [`json_base_class_t`](json_base_class_t.md) subobject is exchanged along with the value as well, the same way it
|
||||
is copied or moved by the copy/move constructors and assignment operators.
|
||||
3. Exchanges the contents of a JSON array with those of `other`. Does not invoke any move, copy, or swap operations on
|
||||
individual elements. All iterators and references remain valid. The past-the-end iterator is invalidated.
|
||||
4. Exchanges the contents of a JSON object with those of `other`. Does not invoke any move, copy, or swap operations on
|
||||
@@ -164,8 +172,8 @@ Constant.
|
||||
|
||||
## Version history
|
||||
|
||||
1. Since version 1.0.0.
|
||||
2. Since version 1.0.0.
|
||||
1. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
|
||||
2. Since version 1.0.0. Exchanges the `json_base_class_t` subobject along with the value since version 3.13.0.
|
||||
3. Since version 1.0.0.
|
||||
4. Since version 1.0.0.
|
||||
5. Since version 1.0.0.
|
||||
|
||||
@@ -336,7 +336,7 @@ void templated_json_throw(ExceptionType exception)
|
||||
return ej_pair.second == j; \
|
||||
}); \
|
||||
if (it != std::end(m)) e = it->first; \
|
||||
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace)), &j)); \
|
||||
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \
|
||||
}
|
||||
|
||||
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
||||
|
||||
@@ -4335,12 +4335,21 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_constructible<value_t>::value&&
|
||||
std::is_nothrow_move_assignable<value_t>::value&&
|
||||
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value&&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value&&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
)
|
||||
{
|
||||
std::swap(m_data.m_type, other.m_data.m_type);
|
||||
std::swap(m_data.m_value, other.m_data.m_value);
|
||||
|
||||
// the custom base class travels with the value when it is copied or
|
||||
// moved, so it is exchanged along with it
|
||||
{
|
||||
using std::swap;
|
||||
swap(static_cast<json_base_class_t&>(*this), static_cast<json_base_class_t&>(other));
|
||||
}
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
std::swap(start_position, other.start_position);
|
||||
std::swap(end_position, other.end_position);
|
||||
@@ -4357,7 +4366,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_constructible<value_t>::value&&
|
||||
std::is_nothrow_move_assignable<value_t>::value&&
|
||||
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value&&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value&&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
)
|
||||
{
|
||||
left.swap(right);
|
||||
|
||||
@@ -2747,7 +2747,7 @@ void templated_json_throw(ExceptionType exception)
|
||||
return ej_pair.second == j; \
|
||||
}); \
|
||||
if (it != std::end(m)) e = it->first; \
|
||||
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410, nlohmann::detail::concat("enum value out of range for " #ENUM_TYPE ": ", j.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace)), &j)); \
|
||||
else templated_json_throw<nlohmann::detail::out_of_range>(nlohmann::detail::out_of_range::create(410,"enum value out of range for " #ENUM_TYPE ": " + j.dump(), &j)); \
|
||||
}
|
||||
|
||||
// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
|
||||
@@ -30416,12 +30416,21 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_constructible<value_t>::value&&
|
||||
std::is_nothrow_move_assignable<value_t>::value&&
|
||||
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value&&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value&&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
)
|
||||
{
|
||||
std::swap(m_data.m_type, other.m_data.m_type);
|
||||
std::swap(m_data.m_value, other.m_data.m_value);
|
||||
|
||||
// the custom base class travels with the value when it is copied or
|
||||
// moved, so it is exchanged along with it
|
||||
{
|
||||
using std::swap;
|
||||
swap(static_cast<json_base_class_t&>(*this), static_cast<json_base_class_t&>(other));
|
||||
}
|
||||
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
std::swap(start_position, other.start_position);
|
||||
std::swap(end_position, other.end_position);
|
||||
@@ -30438,7 +30447,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_constructible<value_t>::value&&
|
||||
std::is_nothrow_move_assignable<value_t>::value&&
|
||||
std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
std::is_nothrow_move_assignable<json_value>::value&&
|
||||
std::is_nothrow_move_constructible<json_base_class_t>::value&&
|
||||
std::is_nothrow_move_assignable<json_base_class_t>::value
|
||||
)
|
||||
{
|
||||
left.swap(right);
|
||||
|
||||
@@ -174,15 +174,6 @@ bool operator<(const char* op1, const alt_string& op2) noexcept
|
||||
return op1 < op2.str_impl;
|
||||
}
|
||||
|
||||
enum class alt_color { red, green };
|
||||
|
||||
// NOLINTNEXTLINE(misc-use-internal-linkage,misc-const-correctness,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - false positive
|
||||
NLOHMANN_JSON_SERIALIZE_ENUM_STRICT(alt_color,
|
||||
{
|
||||
{alt_color::red, "red"},
|
||||
{alt_color::green, "green"},
|
||||
})
|
||||
|
||||
TEST_CASE("alternative string type")
|
||||
{
|
||||
SECTION("binary formats")
|
||||
@@ -383,19 +374,4 @@ TEST_CASE("alternative string type")
|
||||
const auto j2 = j.flatten();
|
||||
CHECK(j2.dump() == R"({"/foo/0":"bar","/foo/1":"baz"})");
|
||||
}
|
||||
|
||||
SECTION("strict enum")
|
||||
{
|
||||
// regression test for #5667: NLOHMANN_JSON_SERIALIZE_ENUM_STRICT's from_json
|
||||
// built its exception message with "..." + j.dump(), which does not compile
|
||||
// when j.dump() returns a custom string_t (here alt_string) instead of
|
||||
// std::string
|
||||
alt_json doc;
|
||||
doc = "red";
|
||||
CHECK(doc.get<alt_color>() == alt_color::red);
|
||||
|
||||
alt_json _;
|
||||
doc = "blue";
|
||||
CHECK_THROWS_WITH_AS(_ = doc.get<alt_color>(), "[json.exception.out_of_range.410] enum value out of range for alt_color: \"blue\"", alt_json::out_of_range&);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1740,12 +1740,6 @@ TEST_CASE("Strict JSON to enum mapping")
|
||||
|
||||
// conversion of unmapped enum -> exception thrown
|
||||
CHECK_THROWS_WITH_AS(json(strict_cards::andere), "[json.exception.out_of_range.410] enum value out of range for strict_cards", json::out_of_range&);
|
||||
|
||||
// invalid UTF-8 -> out_of_range.410, not the type_error.316 thrown while building the
|
||||
// message (regression test for #5667); such strings can reach get<Enum>() unvalidated,
|
||||
// e.g. from from_cbor()/from_msgpack() (#5529)
|
||||
const json j_invalid_utf8 = "\xFF";
|
||||
CHECK_THROWS_WITH_AS(_ = j_invalid_utf8.get<strict_cards>(), "[json.exception.out_of_range.410] enum value out of range for strict_cards: \"\xEF\xBF\xBD\"", json::out_of_range&);
|
||||
}
|
||||
|
||||
SECTION("traditional enum")
|
||||
|
||||
@@ -6,9 +6,11 @@
|
||||
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
@@ -180,6 +182,76 @@ TEST_CASE("JSON Node Metadata")
|
||||
CHECK(val.metadata().at(1) == 2);
|
||||
}
|
||||
}
|
||||
SECTION("member swap")
|
||||
{
|
||||
using json = json_with_metadata<int>;
|
||||
json a = 1;
|
||||
a.metadata() = 100;
|
||||
json b = 2;
|
||||
b.metadata() = 200;
|
||||
|
||||
a.swap(b);
|
||||
|
||||
CHECK(a.get<int>() == 2);
|
||||
CHECK(b.get<int>() == 1);
|
||||
CHECK(a.metadata() == 200);
|
||||
CHECK(b.metadata() == 100);
|
||||
}
|
||||
SECTION("nonmember swap")
|
||||
{
|
||||
using json = json_with_metadata<int>;
|
||||
json a = 1;
|
||||
a.metadata() = 100;
|
||||
json b = 2;
|
||||
b.metadata() = 200;
|
||||
|
||||
using std::swap;
|
||||
swap(a, b);
|
||||
|
||||
CHECK(a.get<int>() == 2);
|
||||
CHECK(b.get<int>() == 1);
|
||||
CHECK(a.metadata() == 200);
|
||||
CHECK(b.metadata() == 100);
|
||||
}
|
||||
SECTION("std::swap")
|
||||
{
|
||||
using json = json_with_metadata<int>;
|
||||
json a = 1;
|
||||
a.metadata() = 100;
|
||||
json b = 2;
|
||||
b.metadata() = 200;
|
||||
|
||||
std::swap(a, b);
|
||||
|
||||
CHECK(a.get<int>() == 2);
|
||||
CHECK(b.get<int>() == 1);
|
||||
CHECK(a.metadata() == 200);
|
||||
CHECK(b.metadata() == 100);
|
||||
}
|
||||
SECTION("std::sort keeps metadata attached to its value")
|
||||
{
|
||||
// std::sort mixes swap() with moves; each value's metadata must
|
||||
// travel with it, just as it does for copy, move, and assignment
|
||||
using json = json_with_metadata<int>;
|
||||
std::vector<json> values;
|
||||
for (int v :
|
||||
{
|
||||
5, 3, 9, 1, 7, 2, 8, 4, 6, 0, 15, 13, 19, 11, 17, 12, 18, 14, 16, 10,
|
||||
25, 23, 29, 21, 27, 22, 28, 24, 26, 20, 35, 33
|
||||
})
|
||||
{
|
||||
json value = v;
|
||||
value.metadata() = v;
|
||||
values.push_back(value);
|
||||
}
|
||||
|
||||
std::sort(values.begin(), values.end());
|
||||
|
||||
for (const auto& value : values)
|
||||
{
|
||||
CHECK(value.metadata() == value.get<int>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test extending nlohmann::json by using a custom base class.
|
||||
|
||||
Reference in New Issue
Block a user