mirror of
https://github.com/nlohmann/json.git
synced 2026-10-02 12:40:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c266a10a8 | ||
|
|
6a073dbae4 | ||
|
|
fdcc569eee | ||
|
|
4ab78e8092 | ||
|
|
10c0d41f7c | ||
|
|
de261db5ae | ||
|
|
013923dc89 | ||
|
|
82601da6ec | ||
|
|
1cd636bd61 |
@@ -16,6 +16,7 @@ INSERT INTO searchIndex(name, type, path) VALUES ('basic_json', 'Class', 'api/ba
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::accept', 'Function', 'api/basic_json/accept/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array', 'Function', 'api/basic_json/array/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::array_t', 'Type', 'api/basic_json/array_t/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::as_base_class', 'Method', 'api/basic_json/as_base_class/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::at', 'Method', 'api/basic_json/at/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::back', 'Method', 'api/basic_json/back/index.html');
|
||||
INSERT INTO searchIndex(name, type, path) VALUES ('basic_json::basic_json', 'Constructor', 'api/basic_json/basic_json/index.html');
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
# <small>nlohmann::basic_json::</small>as_base_class
|
||||
|
||||
```cpp
|
||||
json_base_class_t& as_base_class() noexcept;
|
||||
const json_base_class_t& as_base_class() const noexcept;
|
||||
```
|
||||
|
||||
Returns a reference to this object as its custom base class [`json_base_class_t`](json_base_class_t.md). No copy is
|
||||
made.
|
||||
|
||||
Since `basic_json` derives from `json_base_class_t`, a member of `basic_json` hides any member of the custom base class
|
||||
with the same name. This function makes such hidden members accessible again.
|
||||
|
||||
## Return value
|
||||
|
||||
reference to this object as [`json_base_class_t`](json_base_class_t.md)
|
||||
|
||||
## Exception safety
|
||||
|
||||
No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
## Complexity
|
||||
|
||||
Constant.
|
||||
|
||||
## Notes
|
||||
|
||||
The function is equivalent to `static_cast<json_base_class_t&>(j)` (or `static_cast<const json_base_class_t&>(j)`).
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
|
||||
The example shows how to use `as_base_class` to access members of the custom base class that are hidden by members
|
||||
of `basic_json`.
|
||||
|
||||
```cpp
|
||||
--8<-- "examples/as_base_class.cpp"
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
```json
|
||||
--8<-- "examples/as_base_class.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [json_base_class_t](json_base_class_t.md) - type of the custom base class
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.13.0.
|
||||
@@ -200,6 +200,7 @@ Direct access to the stored value of a JSON value.
|
||||
- [**get_ref**](get_ref.md) - get a reference value
|
||||
- [**operator ValueType**](operator_ValueType.md) - get a value
|
||||
- [**get_binary**](get_binary.md) - get a binary value
|
||||
- [**as_base_class**](as_base_class.md) - access the custom base class
|
||||
|
||||
### Element access
|
||||
|
||||
|
||||
@@ -27,6 +27,18 @@ A `CustomBaseClass` with non-static data members forfeits `basic_json`'s
|
||||
[standard layout](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType) guarantee. See
|
||||
[Template Parameter Requirements](../../features/types/template_parameters.md#custombaseclass).
|
||||
|
||||
#### Name conflicts
|
||||
|
||||
Since `basic_json` derives from `CustomBaseClass`, members of `basic_json` hide members of `CustomBaseClass` with the
|
||||
same name. Hidden members remain accessible via [`as_base_class`](as_base_class.md) or by casting the value to
|
||||
`json_base_class_t`.
|
||||
|
||||
!!! warning "Avoid generic member names"
|
||||
|
||||
Future versions of the library may add members to `basic_json` that hide members of `CustomBaseClass` that are
|
||||
accessible today. To reduce the risk of such conflicts, avoid generic names for the members of `CustomBaseClass`,
|
||||
for instance by using a distinctive prefix.
|
||||
|
||||
## Examples
|
||||
|
||||
??? example
|
||||
@@ -43,6 +55,11 @@ A `CustomBaseClass` with non-static data members forfeits `basic_json`'s
|
||||
--8<-- "examples/json_base_class_t.output"
|
||||
```
|
||||
|
||||
## See also
|
||||
|
||||
- [as_base_class](as_base_class.md) - access the custom base class
|
||||
|
||||
## Version history
|
||||
|
||||
- Added in version 3.12.0.
|
||||
- Made a public member type in version 3.13.0; it was private before, so it could not be named outside the class.
|
||||
|
||||
@@ -18,6 +18,10 @@ Deserializes an input stream to a JSON value.
|
||||
|
||||
the stream `i`
|
||||
|
||||
## Exception safety
|
||||
|
||||
Strong guarantee: if an exception is thrown, there are no changes in `j`.
|
||||
|
||||
## Exceptions
|
||||
|
||||
- Throws [`parse_error.101`](../home/exceptions.md#jsonexceptionparse_error101) in case of an unexpected token, or if
|
||||
@@ -125,3 +129,5 @@ being read.
|
||||
the stream; planned to become the default in version 4.0.0.
|
||||
- Fixed a null pointer dereference for an `std::istream` without a stream buffer (now throws `parse_error.101`), and a
|
||||
crash (`std::terminate`) when `i` has `eofbit` in its exception mask, in version 3.13.0.
|
||||
- Changed to the strong exception safety guarantee in version 3.13.0: `j` is no longer left with a partially parsed
|
||||
value if parsing throws.
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#include <iostream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
class base_class_with_hidden_members
|
||||
{
|
||||
public:
|
||||
const char* type_name() const noexcept
|
||||
{
|
||||
return "my_type_name";
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept
|
||||
{
|
||||
return 42;
|
||||
}
|
||||
};
|
||||
|
||||
using json = nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
base_class_with_hidden_members
|
||||
>;
|
||||
|
||||
int main()
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
|
||||
// the members of basic_json hide the members of the base class
|
||||
std::cout << j.type_name() << ' ' << j.size() << '\n';
|
||||
|
||||
// access the hidden members of the base class
|
||||
std::cout << j.as_base_class().type_name() << ' ' << j.as_base_class().size() << '\n';
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
array 3
|
||||
my_type_name 42
|
||||
@@ -389,6 +389,7 @@ using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
|
||||
| Functionality | Additional requirement |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| [`diff`](../../api/basic_json/diff.md), [`items`](../../api/basic_json/items.md), [`std::hash`](../../api/basic_json/std_hash.md) | conversion of a `#!cpp std::size_t` to `StringType`: either assignability from the result of `#!cpp std::to_string`, or an ADL overload `#!cpp void int_to_string(StringType&, std::size_t)` |
|
||||
| [`operator/(std::size_t)`](../../api/json_pointer/operator_slash.md) | the same conversion of a `#!cpp std::size_t` to `StringType` as `diff`, `items`, and `std::hash` above |
|
||||
| [`std::hash<basic_json>`](../../api/basic_json/std_hash.md) | additionally a specialization of `#!cpp std::hash<StringType>` |
|
||||
| [`to_bson`](../../api/basic_json/to_bson.md) | `find(value_type)` and `npos` |
|
||||
| [`parse`](../../api/basic_json/parse.md) from a `string_t` | the input adapters must accept it; otherwise pass a character range |
|
||||
|
||||
@@ -114,6 +114,7 @@ nav:
|
||||
- 'accept': api/basic_json/accept.md
|
||||
- 'array': api/basic_json/array.md
|
||||
- 'array_t': api/basic_json/array_t.md
|
||||
- 'as_base_class': api/basic_json/as_base_class.md
|
||||
- 'at': api/basic_json/at.md
|
||||
- 'back': api/basic_json/back.md
|
||||
- 'begin': api/basic_json/begin.md
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/string_concat.hpp>
|
||||
#include <nlohmann/detail/string_escape.hpp>
|
||||
#include <nlohmann/detail/string_utils.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
@@ -116,7 +117,7 @@ class json_pointer
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||
json_pointer& operator/=(std::size_t array_idx)
|
||||
{
|
||||
return *this /= std::to_string(array_idx);
|
||||
return *this /= detail::to_string<string_t>(array_idx);
|
||||
}
|
||||
|
||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||
@@ -752,7 +753,7 @@ class json_pointer
|
||||
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
||||
return false;
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !('0' <= reference_token[0] && reference_token[0] <= '9')))
|
||||
{
|
||||
// invalid char
|
||||
return false;
|
||||
@@ -780,7 +781,7 @@ class json_pointer
|
||||
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||
errno = 0; // strtoull() does not reset errno on success
|
||||
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
||||
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||
{
|
||||
|
||||
@@ -155,7 +155,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// workaround type for MSVC
|
||||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
// convenience aliases for types residing in namespace detail;
|
||||
@@ -215,6 +214,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
|
||||
/// how to encode BJData
|
||||
using bjdata_version_t = detail::bjdata_version_t;
|
||||
/// base class used to inject custom functionality into each instance of basic_json
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/json_base_class_t/
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
/// helper type for initializer lists of basic_json values
|
||||
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||
|
||||
@@ -2691,6 +2693,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return *get_ptr<const binary_t*>();
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
json_base_class_t& as_base_class() noexcept
|
||||
{
|
||||
return static_cast<json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
const json_base_class_t& as_base_class() const noexcept
|
||||
{
|
||||
return static_cast<const json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////
|
||||
@@ -5092,7 +5108,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
||||
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
||||
{
|
||||
parser(detail::input_adapter(i)).parse(false, j);
|
||||
// parse into a temporary so that j is left unchanged if parsing fails
|
||||
basic_json result;
|
||||
parser(detail::input_adapter(i)).parse(false, result);
|
||||
j = std::move(result);
|
||||
return i;
|
||||
}
|
||||
#endif // JSON_NO_IO
|
||||
|
||||
@@ -19636,6 +19636,8 @@ NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
// #include <nlohmann/detail/string_escape.hpp>
|
||||
|
||||
// #include <nlohmann/detail/string_utils.hpp>
|
||||
|
||||
// #include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
|
||||
@@ -19727,7 +19729,7 @@ class json_pointer
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||
json_pointer& operator/=(std::size_t array_idx)
|
||||
{
|
||||
return *this /= std::to_string(array_idx);
|
||||
return *this /= detail::to_string<string_t>(array_idx);
|
||||
}
|
||||
|
||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||
@@ -20363,7 +20365,7 @@ class json_pointer
|
||||
// would throw out_of_range.404 -- contains() must not throw (see #5395)
|
||||
return false;
|
||||
}
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
|
||||
if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !('0' <= reference_token[0] && reference_token[0] <= '9')))
|
||||
{
|
||||
// invalid char
|
||||
return false;
|
||||
@@ -20391,7 +20393,7 @@ class json_pointer
|
||||
// not throw (see #5395), so such a reference token is treated as "not found"
|
||||
errno = 0; // strtoull() does not reset errno on success
|
||||
char* p_end = nullptr; // NOLINT(misc-const-correctness)
|
||||
const unsigned long long magnitude = std::strtoull(reference_token.c_str(), &p_end, 10); // NOLINT(runtime/int)
|
||||
const unsigned long long magnitude = std::strtoull(reference_token.data(), &p_end, 10); // NOLINT(runtime/int)
|
||||
if (JSON_HEDLEY_UNLIKELY(errno == ERANGE // the value exceeds ULLONG_MAX
|
||||
|| magnitude >= static_cast<unsigned long long>((std::numeric_limits<typename BasicJsonType::size_type>::max)()))) // NOLINT(runtime/int)
|
||||
{
|
||||
@@ -27080,7 +27082,6 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
/// workaround type for MSVC
|
||||
using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
|
||||
JSON_PRIVATE_UNLESS_TESTED:
|
||||
// convenience aliases for types residing in namespace detail;
|
||||
@@ -27140,6 +27141,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
using cbor_tag_handler_t = detail::cbor_tag_handler_t;
|
||||
/// how to encode BJData
|
||||
using bjdata_version_t = detail::bjdata_version_t;
|
||||
/// base class used to inject custom functionality into each instance of basic_json
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/json_base_class_t/
|
||||
using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
|
||||
/// helper type for initializer lists of basic_json values
|
||||
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||
|
||||
@@ -29616,6 +29620,20 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
return *get_ptr<const binary_t*>();
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
json_base_class_t& as_base_class() noexcept
|
||||
{
|
||||
return static_cast<json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @brief access the custom base class
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/as_base_class/
|
||||
const json_base_class_t& as_base_class() const noexcept
|
||||
{
|
||||
return static_cast<const json_base_class_t&>(*this);
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
////////////////////
|
||||
@@ -32017,7 +32035,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
|
||||
friend std::istream& operator>>(std::istream& i, basic_json& j)
|
||||
{
|
||||
parser(detail::input_adapter(i)).parse(false, j);
|
||||
// parse into a temporary so that j is left unchanged if parsing fails
|
||||
basic_json result;
|
||||
parser(detail::input_adapter(i)).parse(false, result);
|
||||
j = std::move(result);
|
||||
return i;
|
||||
}
|
||||
#endif // JSON_NO_IO
|
||||
|
||||
@@ -352,6 +352,41 @@ TEST_CASE("alternative string type")
|
||||
CHECK(j2.flatten().unflatten() == j2);
|
||||
}
|
||||
|
||||
SECTION("contains(json_pointer)")
|
||||
{
|
||||
// contains(json_pointer) must compile and work with a string_t that has
|
||||
// no c_str() and no comparison with const char* (see #5666)
|
||||
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||
|
||||
// present: object key and array indices
|
||||
CHECK(j.contains(alt_json::json_pointer("/foo")));
|
||||
CHECK(j.contains(alt_json::json_pointer("/foo/0")));
|
||||
CHECK(j.contains(alt_json::json_pointer("/foo/1")));
|
||||
|
||||
// missing: absent object key and out-of-range array index
|
||||
CHECK_FALSE(j.contains(alt_json::json_pointer("/bar")));
|
||||
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/2")));
|
||||
|
||||
// "-" always fails the range check
|
||||
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/-")));
|
||||
|
||||
// an array index must not have a leading zero
|
||||
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/01")));
|
||||
|
||||
// a reference token that is not a number
|
||||
CHECK_FALSE(j.contains(alt_json::json_pointer("/foo/bar")));
|
||||
}
|
||||
|
||||
SECTION("operator/(std::size_t)")
|
||||
{
|
||||
// json_pointer::operator/=(std::size_t) must compile without string_t
|
||||
// being constructible from std::string (see #5666)
|
||||
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||
|
||||
CHECK(j.at(alt_json::json_pointer("/foo") / std::size_t(0)) == j["foo"][0]);
|
||||
CHECK(j.at(alt_json::json_pointer("/foo") / std::size_t(1)) == j["foo"][1]);
|
||||
}
|
||||
|
||||
SECTION("patch")
|
||||
{
|
||||
alt_json const patch1 = alt_json::parse(R"([{ "op": "add", "path": "/a/b", "value": [ "foo", "bar" ] }])");
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
@@ -405,3 +407,71 @@ TEST_CASE("JSON Visit Node")
|
||||
);
|
||||
CHECK(expected.empty());
|
||||
}
|
||||
|
||||
// Test accessing members of a custom base class that are hidden by members of nlohmann::basic_json
|
||||
class base_class_with_hidden_members
|
||||
{
|
||||
public:
|
||||
const char* type_name() const noexcept // NOLINT(readability-convert-member-functions-to-static)
|
||||
{
|
||||
return "custom type_name";
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
std::size_t m_size = 42;
|
||||
};
|
||||
|
||||
using json_with_hidden_base_members =
|
||||
nlohmann::basic_json <
|
||||
std::map,
|
||||
std::vector,
|
||||
std::string,
|
||||
bool,
|
||||
std::int64_t,
|
||||
std::uint64_t,
|
||||
double,
|
||||
std::allocator,
|
||||
nlohmann::adl_serializer,
|
||||
std::vector<std::uint8_t>,
|
||||
base_class_with_hidden_members
|
||||
>;
|
||||
|
||||
TEST_CASE("JSON Node as_base_class")
|
||||
{
|
||||
using json = json_with_hidden_base_members;
|
||||
|
||||
static_assert(std::is_same<decltype(std::declval<json&>().as_base_class()), json::json_base_class_t&>::value, "");
|
||||
static_assert(std::is_same<decltype(std::declval<const json&>().as_base_class()), const json::json_base_class_t&>::value, "");
|
||||
static_assert(noexcept(std::declval<json&>().as_base_class()), "");
|
||||
static_assert(noexcept(std::declval<const json&>().as_base_class()), "");
|
||||
|
||||
SECTION("non-const")
|
||||
{
|
||||
json j = {1, 2, 3};
|
||||
|
||||
CHECK(std::string(j.type_name()) == "array");
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(std::string(j.as_base_class().type_name()) == "custom type_name");
|
||||
CHECK(j.as_base_class().size() == 42);
|
||||
CHECK(&j.as_base_class() == &static_cast<json::json_base_class_t&>(j));
|
||||
|
||||
j.as_base_class().m_size = 7;
|
||||
CHECK(j.as_base_class().size() == 7);
|
||||
CHECK(j.size() == 3);
|
||||
}
|
||||
|
||||
SECTION("const")
|
||||
{
|
||||
const json j = {1, 2, 3};
|
||||
|
||||
CHECK(std::string(j.type_name()) == "array");
|
||||
CHECK(j.size() == 3);
|
||||
CHECK(std::string(j.as_base_class().type_name()) == "custom type_name");
|
||||
CHECK(j.as_base_class().size() == 42);
|
||||
CHECK(&j.as_base_class() == &static_cast<const json::json_base_class_t&>(j));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ using nlohmann::json;
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <sstream>
|
||||
|
||||
TEST_CASE("Better diagnostics")
|
||||
{
|
||||
@@ -492,6 +493,21 @@ TEST_CASE("Regression tests for extended diagnostics")
|
||||
CHECK(copy == j);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("Regression test for issue #5652 - operator>> leaves a partial value in its target on a parse error")
|
||||
{
|
||||
json j = "old value";
|
||||
std::istringstream is("[1, x");
|
||||
CHECK_THROWS_WITH_AS(is >> j, "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '1, x'", json::parse_error);
|
||||
|
||||
// j must be left unchanged, as json::parse() guarantees for its result
|
||||
CHECK(j == "old value");
|
||||
|
||||
// copying j must not trigger assert_invariant(): a failed parse must
|
||||
// not leave array/object elements without a parent pointer
|
||||
json const copy = j; // NOLINT(performance-unnecessary-copy-initialization)
|
||||
CHECK(copy == j);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Better diagnostics past the descent bound of update() and merge_patch()")
|
||||
|
||||
Reference in New Issue
Block a user