mirror of
https://github.com/nlohmann/json.git
synced 2026-09-28 02:30:32 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dc43e8bf8 | ||
|
|
e0eb3e7490 | ||
|
|
3ae4d7c45e |
@@ -272,6 +272,15 @@ basic_json(basic_json&& other) noexcept;
|
||||
When used without parentheses around an empty initializer list, `basic_json()` is called instead of this
|
||||
function, yielding the JSON `#!json null` value.
|
||||
|
||||
- Overload 4:
|
||||
|
||||
!!! info "Implicit conversion"
|
||||
|
||||
The conversion is implicit unless [`JSON_USE_IMPLICIT_CONVERSIONS`](../macros/json_use_implicit_conversions.md)
|
||||
is defined to `0` and `BasicJsonType::string_t` differs from `string_t`. In that case, the constructor is
|
||||
`explicit`, so a JSON value with a different string type is no longer silently converted, for example when it is
|
||||
passed to a function taking `#!cpp const json&`. Write `#!cpp json(other)` or `#!cpp other.get<json>()` instead.
|
||||
|
||||
- Overload 7:
|
||||
|
||||
!!! info "Preconditions"
|
||||
@@ -420,7 +429,8 @@ basic_json(basic_json&& other) noexcept;
|
||||
1. Since version 1.0.0.
|
||||
2. Since version 1.0.0.
|
||||
3. Since version 2.1.0.
|
||||
4. Since version 3.2.0.
|
||||
4. Since version 3.2.0. Explicit for different string types if `JSON_USE_IMPLICIT_CONVERSIONS` is `0` since
|
||||
version 3.13.0.
|
||||
5. Since version 1.0.0.
|
||||
6. Since version 1.0.0.
|
||||
7. Since version 1.0.0.
|
||||
|
||||
@@ -80,8 +80,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
the end of the file was not reached when `strict` was set to true
|
||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from CBOR were
|
||||
used in the given input or if the input is not valid CBOR
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
||||
but not found
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -73,8 +73,8 @@ Strong guarantee: if an exception is thrown, there are no changes in the JSON va
|
||||
the end of the file was not reached when `strict` was set to true
|
||||
- Throws [parse_error.112](../../home/exceptions.md#jsonexceptionparse_error112) if unsupported features from
|
||||
MessagePack were used in the given input or if the input is not valid MessagePack
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a map key is not a string (keys of other
|
||||
types are not supported, as JSON object keys are always strings) or a string is malformed
|
||||
- Throws [parse_error.113](../../home/exceptions.md#jsonexceptionparse_error113) if a string was expected as a map key,
|
||||
but not found
|
||||
|
||||
## Complexity
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
```
|
||||
|
||||
When defined to `0`, implicit conversions are switched off. By default, implicit conversions are switched on. The
|
||||
value directly affects [`operator ValueType`](../basic_json/operator_ValueType.md).
|
||||
value directly affects [`operator ValueType`](../basic_json/operator_ValueType.md) and the
|
||||
[converting constructor](../basic_json/basic_json.md) from a `basic_json` specialization with a different string
|
||||
type (overload 4).
|
||||
|
||||
## Default definition
|
||||
|
||||
@@ -57,6 +59,25 @@ By default, implicit conversions are enabled.
|
||||
auto s = j.get<std::string>();
|
||||
```
|
||||
|
||||
??? example "Conversion between `basic_json` specializations"
|
||||
|
||||
A `basic_json` specialization with a different string type is also no longer converted implicitly when
|
||||
`JSON_USE_IMPLICIT_CONVERSIONS` is defined to `0`:
|
||||
|
||||
```cpp
|
||||
using wjson = nlohmann::basic_json<std::map, std::vector, std::wstring>;
|
||||
|
||||
void load(const nlohmann::json& j);
|
||||
|
||||
wjson wj = /* ... */;
|
||||
load(wj); // error: no implicit conversion
|
||||
load(nlohmann::json(wj)); // OK: explicit conversion
|
||||
load(wj.get<nlohmann::json>()); // OK: explicit conversion
|
||||
```
|
||||
|
||||
Specializations that share the same string type, such as `json` and `ordered_json`, remain implicitly
|
||||
convertible.
|
||||
|
||||
## See also
|
||||
|
||||
- [**operator ValueType**](../basic_json/operator_ValueType.md) - get a value (implicit)
|
||||
@@ -66,3 +87,4 @@ By default, implicit conversions are enabled.
|
||||
## Version history
|
||||
|
||||
- Added in version 3.9.0.
|
||||
- Also affects the conversion between `basic_json` specializations with different string types since version 3.13.0.
|
||||
|
||||
@@ -174,20 +174,7 @@ The library maps CBOR types to JSON value types as follows:
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps
|
||||
with keys other than text strings (major type 3) are rejected with a
|
||||
[`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with `allow_exceptions` set
|
||||
to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||
```
|
||||
|
||||
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||
on. This is a deliberate restriction of the library's JSON value model, not an oversight: formats built on CBOR
|
||||
maps with integer keys, such as COSE ([RFC 9052](https://www.rfc-editor.org/rfc/rfc9052.html)) or CWT
|
||||
([RFC 8392](https://www.rfc-editor.org/rfc/rfc8392.html)), cannot be read with this library and need a
|
||||
general-purpose CBOR library instead.
|
||||
CBOR allows map keys of any type, whereas JSON only allows strings as keys in object values. Therefore, CBOR maps with keys other than UTF-8 strings are rejected.
|
||||
|
||||
!!! warning "UTF-8 validation of text strings"
|
||||
|
||||
|
||||
@@ -138,21 +138,6 @@ The library maps MessagePack types to JSON value types as follows:
|
||||
|
||||
Any MessagePack output created by `to_msgpack` can be successfully parsed by `from_msgpack`.
|
||||
|
||||
!!! warning "Object keys"
|
||||
|
||||
MessagePack allows map keys of any type, whereas JSON only allows strings as keys in object values. Like the
|
||||
JSON-compatible [profile](https://github.com/msgpack/msgpack/blob/master/spec.md#profile) sketched in the
|
||||
MessagePack specification, this library restricts map keys to `str` values. Maps with keys of any other type are
|
||||
rejected with a [`parse_error.113`](../../home/exceptions.md#jsonexceptionparse_error113) exception (or, with
|
||||
`allow_exceptions` set to `false`, a discarded value) naming the type of the key that was found, for instance:
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||
```
|
||||
|
||||
This applies to the [SAX interface](../parsing/sax_interface.md) as well, as the key is read before it is passed
|
||||
on. Such input needs a general-purpose MessagePack library instead.
|
||||
|
||||
!!! warning "UTF-8 validation of string values"
|
||||
|
||||
The MessagePack specification requires `str` values (`fixstr`, `str 8`, `str 16`, `str 32`) to be valid UTF-8.
|
||||
|
||||
@@ -343,20 +343,13 @@ A string could not be read from a [binary format](../features/binary_formats/ind
|
||||
string was read where one was required (for instance as a map key), the string's length specification is invalid, or
|
||||
the string's bytes are not valid UTF-8.
|
||||
|
||||
CBOR and MessagePack allow map keys of any type, but JSON object keys are always strings. Maps with keys of any other
|
||||
type (for instance integers or `null`) are therefore not supported; see the notes on
|
||||
[CBOR](../features/binary_formats/cbor.md) and [MessagePack](../features/binary_formats/messagepack.md).
|
||||
|
||||
!!! failure "Example messages"
|
||||
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an unsigned integer; last byte: 0x01
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found nil; last byte: 0xC0
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x7C
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF
|
||||
```
|
||||
```
|
||||
[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82
|
||||
|
||||
@@ -291,7 +291,9 @@ void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
j = *opt;
|
||||
// explicit construction, as the conversion from a basic_json with a different
|
||||
// string type is explicit if JSON_USE_IMPLICIT_CONVERSIONS is 0 (#2649)
|
||||
j = BasicJsonType(*opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -1324,80 +1324,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR object key
|
||||
|
||||
RFC 8949 allows any data item as a map key, but only strings have a
|
||||
counterpart in JSON. A key of any other type is rejected with a message
|
||||
naming that type, rather than the one @ref get_cbor_string gives for a
|
||||
malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_cbor_object_key(string_t& result)
|
||||
{
|
||||
// EOF and major type 3 (text string) are left to get_cbor_string
|
||||
if (current == char_traits<char_type>::eof() || (static_cast<unsigned int>(current) & 0xE0u) == 0x60u)
|
||||
{
|
||||
return get_cbor_string(result);
|
||||
}
|
||||
|
||||
const char* found = nullptr;
|
||||
switch (static_cast<unsigned int>(current) >> 5u)
|
||||
{
|
||||
case 0:
|
||||
found = "an unsigned integer";
|
||||
break;
|
||||
case 1:
|
||||
found = "a negative integer";
|
||||
break;
|
||||
case 2:
|
||||
found = "a byte string";
|
||||
break;
|
||||
case 4:
|
||||
found = "an array";
|
||||
break;
|
||||
case 5:
|
||||
found = "a map";
|
||||
break;
|
||||
case 6:
|
||||
found = "a tag";
|
||||
break;
|
||||
default: // major type 7
|
||||
switch (current)
|
||||
{
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xF6:
|
||||
found = "null";
|
||||
break;
|
||||
case 0xF7:
|
||||
found = "undefined";
|
||||
break;
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
found = "a floating-point number";
|
||||
break;
|
||||
case 0xFF:
|
||||
found = "a break stop code";
|
||||
break;
|
||||
default:
|
||||
found = "a simple value";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
@@ -1642,7 +1568,7 @@ class binary_reader
|
||||
if (top.is_object)
|
||||
{
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -2143,98 +2069,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack object key
|
||||
|
||||
The MessagePack specification allows any type as a map key, but only
|
||||
strings have a counterpart in JSON. A key of any other type is rejected
|
||||
with a message naming that type, rather than the one @ref
|
||||
get_msgpack_string gives for a malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_msgpack_object_key(string_t& result)
|
||||
{
|
||||
const char* found = nullptr;
|
||||
switch (current)
|
||||
{
|
||||
case 0xC0:
|
||||
found = "nil";
|
||||
break;
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
found = "a float";
|
||||
break;
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
found = "a bin";
|
||||
break;
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
found = "an ext";
|
||||
break;
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
found = "an integer";
|
||||
break;
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
found = "an array";
|
||||
break;
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
found = "a map";
|
||||
break;
|
||||
default:
|
||||
// fixint, fixmap, and fixarray; strings, EOF, and the unused
|
||||
// byte 0xC1 are left to get_msgpack_string
|
||||
if (current == char_traits<char_type>::eof())
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
if (current <= 0x7F || current >= 0xE0)
|
||||
{
|
||||
found = "an integer";
|
||||
}
|
||||
else if (current <= 0x8F)
|
||||
{
|
||||
found = "a map";
|
||||
}
|
||||
else if (current <= 0x9F)
|
||||
{
|
||||
found = "an array";
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack byte array
|
||||
|
||||
@@ -2397,7 +2231,7 @@ class binary_reader
|
||||
{
|
||||
get();
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1605,12 +1605,42 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
private:
|
||||
/// whether a basic_json specialization can be converted implicitly into this one;
|
||||
/// with JSON_USE_IMPLICIT_CONVERSIONS set to 0, this is only the case if both share
|
||||
/// the same string type (see https://github.com/nlohmann/json/issues/2649)
|
||||
template<typename BasicJsonType>
|
||||
using is_implicitly_convertible_basic_json = std::integral_constant < bool,
|
||||
(JSON_USE_IMPLICIT_CONVERSIONS != 0)
|
||||
|| std::is_same<typename BasicJsonType::string_t, string_t>::value >;
|
||||
|
||||
/// tag to select the constructor that performs the conversion from another basic_json specialization
|
||||
struct convert_basic_json_tag {};
|
||||
|
||||
public:
|
||||
/// @brief create a JSON value from an existing one
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
template < typename BasicJsonType,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value
|
||||
&& is_implicitly_convertible_basic_json<BasicJsonType>::value, int > = 0 >
|
||||
basic_json(const BasicJsonType& val)
|
||||
: basic_json(val, convert_basic_json_tag{})
|
||||
{}
|
||||
|
||||
/// @brief create a JSON value from an existing one
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
template < typename BasicJsonType,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value
|
||||
&& !is_implicitly_convertible_basic_json<BasicJsonType>::value, int > = 0 >
|
||||
explicit basic_json(const BasicJsonType& val)
|
||||
: basic_json(val, convert_basic_json_tag{})
|
||||
{}
|
||||
|
||||
private:
|
||||
template<typename BasicJsonType>
|
||||
basic_json(const BasicJsonType& val, convert_basic_json_tag /*unused*/)
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
: start_position(val.start_pos()),
|
||||
end_position(val.end_pos())
|
||||
@@ -1666,6 +1696,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief create a container (array or object) from an initializer list
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
basic_json(initializer_list_t init,
|
||||
@@ -2432,7 +2463,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
int > = 0 >
|
||||
BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
|
||||
{
|
||||
return *this;
|
||||
return BasicJsonType(*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2571,7 +2602,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
int> = 0>
|
||||
ValueType & get_to(ValueType& v) const
|
||||
{
|
||||
v = *this;
|
||||
v = ValueType(*this);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -6820,7 +6820,9 @@ void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
|
||||
{
|
||||
if (opt.has_value())
|
||||
{
|
||||
j = *opt;
|
||||
// explicit construction, as the conversion from a basic_json with a different
|
||||
// string type is explicit if JSON_USE_IMPLICIT_CONVERSIONS is 0 (#2649)
|
||||
j = BasicJsonType(*opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -14059,80 +14061,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a CBOR object key
|
||||
|
||||
RFC 8949 allows any data item as a map key, but only strings have a
|
||||
counterpart in JSON. A key of any other type is rejected with a message
|
||||
naming that type, rather than the one @ref get_cbor_string gives for a
|
||||
malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_cbor_object_key(string_t& result)
|
||||
{
|
||||
// EOF and major type 3 (text string) are left to get_cbor_string
|
||||
if (current == char_traits<char_type>::eof() || (static_cast<unsigned int>(current) & 0xE0u) == 0x60u)
|
||||
{
|
||||
return get_cbor_string(result);
|
||||
}
|
||||
|
||||
const char* found = nullptr;
|
||||
switch (static_cast<unsigned int>(current) >> 5u)
|
||||
{
|
||||
case 0:
|
||||
found = "an unsigned integer";
|
||||
break;
|
||||
case 1:
|
||||
found = "a negative integer";
|
||||
break;
|
||||
case 2:
|
||||
found = "a byte string";
|
||||
break;
|
||||
case 4:
|
||||
found = "an array";
|
||||
break;
|
||||
case 5:
|
||||
found = "a map";
|
||||
break;
|
||||
case 6:
|
||||
found = "a tag";
|
||||
break;
|
||||
default: // major type 7
|
||||
switch (current)
|
||||
{
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xF6:
|
||||
found = "null";
|
||||
break;
|
||||
case 0xF7:
|
||||
found = "undefined";
|
||||
break;
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
found = "a floating-point number";
|
||||
break;
|
||||
case 0xFF:
|
||||
found = "a break stop code";
|
||||
break;
|
||||
default:
|
||||
found = "a simple value";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::cbor, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a definite-length CBOR byte array
|
||||
|
||||
@@ -14377,7 +14305,7 @@ class binary_reader
|
||||
if (top.is_object)
|
||||
{
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -14878,98 +14806,6 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack object key
|
||||
|
||||
The MessagePack specification allows any type as a map key, but only
|
||||
strings have a counterpart in JSON. A key of any other type is rejected
|
||||
with a message naming that type, rather than the one @ref
|
||||
get_msgpack_string gives for a malformed string.
|
||||
|
||||
@param[out] result created key
|
||||
|
||||
@return whether key creation completed
|
||||
*/
|
||||
bool get_msgpack_object_key(string_t& result)
|
||||
{
|
||||
const char* found = nullptr;
|
||||
switch (current)
|
||||
{
|
||||
case 0xC0:
|
||||
found = "nil";
|
||||
break;
|
||||
case 0xC2:
|
||||
case 0xC3:
|
||||
found = "a boolean";
|
||||
break;
|
||||
case 0xCA:
|
||||
case 0xCB:
|
||||
found = "a float";
|
||||
break;
|
||||
case 0xC4:
|
||||
case 0xC5:
|
||||
case 0xC6:
|
||||
found = "a bin";
|
||||
break;
|
||||
case 0xC7:
|
||||
case 0xC8:
|
||||
case 0xC9:
|
||||
case 0xD4:
|
||||
case 0xD5:
|
||||
case 0xD6:
|
||||
case 0xD7:
|
||||
case 0xD8:
|
||||
found = "an ext";
|
||||
break;
|
||||
case 0xCC:
|
||||
case 0xCD:
|
||||
case 0xCE:
|
||||
case 0xCF:
|
||||
case 0xD0:
|
||||
case 0xD1:
|
||||
case 0xD2:
|
||||
case 0xD3:
|
||||
found = "an integer";
|
||||
break;
|
||||
case 0xDC:
|
||||
case 0xDD:
|
||||
found = "an array";
|
||||
break;
|
||||
case 0xDE:
|
||||
case 0xDF:
|
||||
found = "a map";
|
||||
break;
|
||||
default:
|
||||
// fixint, fixmap, and fixarray; strings, EOF, and the unused
|
||||
// byte 0xC1 are left to get_msgpack_string
|
||||
if (current == char_traits<char_type>::eof())
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
if (current <= 0x7F || current >= 0xE0)
|
||||
{
|
||||
found = "an integer";
|
||||
}
|
||||
else if (current <= 0x8F)
|
||||
{
|
||||
found = "a map";
|
||||
}
|
||||
else if (current <= 0x9F)
|
||||
{
|
||||
found = "an array";
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_msgpack_string(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
|
||||
exception_message(input_format_t::msgpack, concat("only string keys are supported, but found ", found, "; last byte: 0x", last_token), "object key"), nullptr));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief reads a MessagePack byte array
|
||||
|
||||
@@ -15132,7 +14968,7 @@ class binary_reader
|
||||
{
|
||||
get();
|
||||
key.clear();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_object_key(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -27654,12 +27490,42 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
private:
|
||||
/// whether a basic_json specialization can be converted implicitly into this one;
|
||||
/// with JSON_USE_IMPLICIT_CONVERSIONS set to 0, this is only the case if both share
|
||||
/// the same string type (see https://github.com/nlohmann/json/issues/2649)
|
||||
template<typename BasicJsonType>
|
||||
using is_implicitly_convertible_basic_json = std::integral_constant < bool,
|
||||
(JSON_USE_IMPLICIT_CONVERSIONS != 0)
|
||||
|| std::is_same<typename BasicJsonType::string_t, string_t>::value >;
|
||||
|
||||
/// tag to select the constructor that performs the conversion from another basic_json specialization
|
||||
struct convert_basic_json_tag {};
|
||||
|
||||
public:
|
||||
/// @brief create a JSON value from an existing one
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
template < typename BasicJsonType,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value
|
||||
&& is_implicitly_convertible_basic_json<BasicJsonType>::value, int > = 0 >
|
||||
basic_json(const BasicJsonType& val)
|
||||
: basic_json(val, convert_basic_json_tag{})
|
||||
{}
|
||||
|
||||
/// @brief create a JSON value from an existing one
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
template < typename BasicJsonType,
|
||||
detail::enable_if_t <
|
||||
detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value
|
||||
&& !is_implicitly_convertible_basic_json<BasicJsonType>::value, int > = 0 >
|
||||
explicit basic_json(const BasicJsonType& val)
|
||||
: basic_json(val, convert_basic_json_tag{})
|
||||
{}
|
||||
|
||||
private:
|
||||
template<typename BasicJsonType>
|
||||
basic_json(const BasicJsonType& val, convert_basic_json_tag /*unused*/)
|
||||
#if JSON_DIAGNOSTIC_POSITIONS
|
||||
: start_position(val.start_pos()),
|
||||
end_position(val.end_pos())
|
||||
@@ -27715,6 +27581,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
public:
|
||||
/// @brief create a container (array or object) from an initializer list
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
basic_json(initializer_list_t init,
|
||||
@@ -28481,7 +28348,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
int > = 0 >
|
||||
BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
|
||||
{
|
||||
return *this;
|
||||
return BasicJsonType(*this);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -28620,7 +28487,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
int> = 0>
|
||||
ValueType & get_to(ValueType& v) const
|
||||
{
|
||||
v = *this;
|
||||
v = ValueType(*this);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@@ -374,4 +375,39 @@ TEST_CASE("alternative string type")
|
||||
const auto j2 = j.flatten();
|
||||
CHECK(j2.dump() == R"({"/foo/0":"bar","/foo/1":"baz"})");
|
||||
}
|
||||
|
||||
SECTION("conversion between basic_json specializations (#2649)")
|
||||
{
|
||||
// explicit conversions are always possible
|
||||
CHECK(std::is_constructible<nlohmann::json, alt_json>::value);
|
||||
CHECK(std::is_constructible<alt_json, nlohmann::json>::value);
|
||||
CHECK(std::is_constructible<nlohmann::json, nlohmann::ordered_json>::value);
|
||||
CHECK(std::is_constructible<nlohmann::ordered_json, nlohmann::json>::value);
|
||||
|
||||
// specializations with the same string type are implicitly convertible
|
||||
CHECK(std::is_convertible<nlohmann::ordered_json, nlohmann::json>::value);
|
||||
CHECK(std::is_convertible<nlohmann::json, nlohmann::ordered_json>::value);
|
||||
|
||||
// specializations with different string types are only implicitly convertible
|
||||
// if implicit conversions are enabled
|
||||
#if JSON_USE_IMPLICIT_CONVERSIONS
|
||||
CHECK(std::is_convertible<alt_json, nlohmann::json>::value);
|
||||
CHECK(std::is_convertible<nlohmann::json, alt_json>::value);
|
||||
#else
|
||||
CHECK_FALSE(std::is_convertible<alt_json, nlohmann::json>::value);
|
||||
CHECK_FALSE(std::is_convertible<nlohmann::json, alt_json>::value);
|
||||
#endif
|
||||
|
||||
// get<BasicJsonType>() works in either case
|
||||
const nlohmann::json j = {{"foo", 1}, {"bar", true}};
|
||||
CHECK(j.get<nlohmann::ordered_json>() == nlohmann::ordered_json(j));
|
||||
// (only a number is converted here, as objects and strings are affected by #3425)
|
||||
CHECK(nlohmann::json(42).get<alt_json>() == 42);
|
||||
CHECK(alt_json(nlohmann::json(42)) == 42);
|
||||
|
||||
// get_to() also works in either case
|
||||
alt_json a;
|
||||
nlohmann::json(42).get_to(a);
|
||||
CHECK(a == 42);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-43
@@ -1830,51 +1830,10 @@ TEST_CASE("CBOR")
|
||||
SECTION("invalid string in map")
|
||||
{
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found a break stop code; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
||||
CHECK(json::from_cbor(std::vector<uint8_t>({0xa1, 0xff, 0x01}), true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("non-string key (see #2766 and #3381)")
|
||||
{
|
||||
// only text strings map to JSON object keys; any other key is
|
||||
// rejected with a message naming its type
|
||||
const std::vector<std::pair<std::vector<std::uint8_t>, std::string>> cases =
|
||||
{
|
||||
{{0xA1, 0x01, 0x01}, "an unsigned integer; last byte: 0x01"},
|
||||
{{0xA1, 0x20, 0x01}, "a negative integer; last byte: 0x20"},
|
||||
{{0xA1, 0x41, 0x61, 0x01}, "a byte string; last byte: 0x41"},
|
||||
{{0xA1, 0x80, 0x01}, "an array; last byte: 0x80"},
|
||||
{{0xA1, 0xA0, 0x01}, "a map; last byte: 0xA0"},
|
||||
{{0xA1, 0xC0, 0x61, 0x61, 0x01}, "a tag; last byte: 0xC0"},
|
||||
{{0xA1, 0xF4, 0x01}, "a boolean; last byte: 0xF4"},
|
||||
{{0xA1, 0xF5, 0x01}, "a boolean; last byte: 0xF5"},
|
||||
{{0xA1, 0xF6, 0x01}, "null; last byte: 0xF6"},
|
||||
{{0xA1, 0xF7, 0x01}, "undefined; last byte: 0xF7"},
|
||||
{{0xA1, 0xF9, 0x3C, 0x00, 0x01}, "a floating-point number; last byte: 0xF9"},
|
||||
{{0xA1, 0xFA, 0x3F, 0x80, 0x00, 0x00, 0x01}, "a floating-point number; last byte: 0xFA"},
|
||||
{{0xA1, 0xFB, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "a floating-point number; last byte: 0xFB"},
|
||||
{{0xA1, 0xE0, 0x01}, "a simple value; last byte: 0xE0"},
|
||||
{{0xA1, 0xF8, 0x20, 0x01}, "a simple value; last byte: 0xF8"},
|
||||
// indefinite-length map
|
||||
{{0xBF, 0x01, 0x01, 0xFF}, "an unsigned integer; last byte: 0x01"},
|
||||
};
|
||||
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
CAPTURE(c.first)
|
||||
const std::string expected = "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found " + c.second;
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(c.first), expected.c_str(), json::parse_error&);
|
||||
CHECK(json::from_cbor(c.first, true, false).is_discarded());
|
||||
}
|
||||
|
||||
// a key of major type 3 with a reserved length is still reported as
|
||||
// a malformed string, and a missing key as the end of input
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing CBOR string: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0x7C, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x7C", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8 in string (see #5529)")
|
||||
{
|
||||
// a two-character text string (major type 3) whose bytes are not
|
||||
@@ -2325,7 +2284,7 @@ TEST_CASE("CBOR indefinite-length strings do not recurse per chunk")
|
||||
SECTION("a break marker outside an indefinite-length string is not a string")
|
||||
{
|
||||
// 0xFF only closes a string that was opened; on its own it is not one
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found a break stop code; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(std::vector<uint8_t>({0xA1, 0xFF, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xFF", json::parse_error&);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1551,69 +1551,10 @@ TEST_CASE("MessagePack")
|
||||
SECTION("invalid string in map")
|
||||
{
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found an integer; last byte: 0xFF", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF", json::parse_error&);
|
||||
CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
|
||||
}
|
||||
|
||||
SECTION("non-string key (see #3381)")
|
||||
{
|
||||
// only strings map to JSON object keys; any other key is rejected
|
||||
// with a message naming its type
|
||||
const std::vector<std::pair<std::vector<std::uint8_t>, std::string>> cases =
|
||||
{
|
||||
{{0x81, 0xC0, 0x01}, "nil; last byte: 0xC0"},
|
||||
{{0x81, 0xC2, 0x01}, "a boolean; last byte: 0xC2"},
|
||||
{{0x81, 0xC3, 0x01}, "a boolean; last byte: 0xC3"},
|
||||
{{0x81, 0xCA, 0x3F, 0x80, 0x00, 0x00, 0x01}, "a float; last byte: 0xCA"},
|
||||
{{0x81, 0xCB, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "a float; last byte: 0xCB"},
|
||||
{{0x81, 0xC4, 0x00, 0x01}, "a bin; last byte: 0xC4"},
|
||||
{{0x81, 0xC5, 0x00, 0x00, 0x01}, "a bin; last byte: 0xC5"},
|
||||
{{0x81, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x01}, "a bin; last byte: 0xC6"},
|
||||
{{0x81, 0xC7, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC7"},
|
||||
{{0x81, 0xC8, 0x00, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC8"},
|
||||
{{0x81, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an ext; last byte: 0xC9"},
|
||||
{{0x81, 0xD4, 0x01, 0x00, 0x01}, "an ext; last byte: 0xD4"},
|
||||
{{0x81, 0xD5, 0x01, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD5"},
|
||||
{{0x81, 0xD6, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD6"},
|
||||
{{0x81, 0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD7"},
|
||||
{{0x81, 0xD8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, "an ext; last byte: 0xD8"},
|
||||
{{0x81, 0xCC, 0x01, 0x01}, "an integer; last byte: 0xCC"},
|
||||
{{0x81, 0xCD, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCD"},
|
||||
{{0x81, 0xCE, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCE"},
|
||||
{{0x81, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xCF"},
|
||||
{{0x81, 0xD0, 0x01, 0x01}, "an integer; last byte: 0xD0"},
|
||||
{{0x81, 0xD1, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD1"},
|
||||
{{0x81, 0xD2, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD2"},
|
||||
{{0x81, 0xD3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01}, "an integer; last byte: 0xD3"},
|
||||
{{0x81, 0x00, 0x01}, "an integer; last byte: 0x00"},
|
||||
{{0x81, 0x7F, 0x01}, "an integer; last byte: 0x7F"},
|
||||
{{0x81, 0xE0, 0x01}, "an integer; last byte: 0xE0"},
|
||||
{{0x81, 0x80, 0x01}, "a map; last byte: 0x80"},
|
||||
{{0x81, 0x8F, 0x01}, "a map; last byte: 0x8F"},
|
||||
{{0x81, 0xDE, 0x00, 0x00, 0x01}, "a map; last byte: 0xDE"},
|
||||
{{0x81, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x01}, "a map; last byte: 0xDF"},
|
||||
{{0x81, 0x90, 0x01}, "an array; last byte: 0x90"},
|
||||
{{0x81, 0x9F, 0x01}, "an array; last byte: 0x9F"},
|
||||
{{0x81, 0xDC, 0x00, 0x00, 0x01}, "an array; last byte: 0xDC"},
|
||||
{{0x81, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x01}, "an array; last byte: 0xDD"},
|
||||
};
|
||||
|
||||
for (const auto& c : cases)
|
||||
{
|
||||
CAPTURE(c.first)
|
||||
const std::string expected = "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack object key: only string keys are supported, but found " + c.second;
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(c.first), expected.c_str(), json::parse_error&);
|
||||
CHECK(json::from_msgpack(c.first, true, false).is_discarded());
|
||||
}
|
||||
|
||||
json _;
|
||||
// the unused byte 0xC1 is still reported as a malformed string
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xC1, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xC1", json::parse_error&);
|
||||
// a missing key is still reported as the end of input
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81})), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("invalid UTF-8 in string (see #5529)")
|
||||
{
|
||||
// a fixstr of length 2 (0xA0 | 2) whose bytes are not valid UTF-8
|
||||
|
||||
@@ -1018,7 +1018,7 @@ TEST_CASE("regression tests 1")
|
||||
};
|
||||
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR object key: only string keys are supported, but found an array; last byte: 0x98", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x98", json::parse_error&);
|
||||
|
||||
// related test case: nonempty UTF-8 string (indefinite length)
|
||||
std::vector<uint8_t> const vec1 {0x7f, 0x61, 0x61};
|
||||
@@ -1065,7 +1065,7 @@ TEST_CASE("regression tests 1")
|
||||
};
|
||||
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR object key: only string keys are supported, but found a map; last byte: 0xB4", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec1), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
|
||||
|
||||
// related test case: double-precision
|
||||
std::vector<uint8_t> const vec2
|
||||
@@ -1077,7 +1077,7 @@ TEST_CASE("regression tests 1")
|
||||
0x96, 0x96, 0xb4, 0xb4, 0xfa, 0x94, 0x94, 0x61,
|
||||
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0xfb
|
||||
};
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR object key: only string keys are supported, but found a map; last byte: 0xB4", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_cbor(vec2), "[json.exception.parse_error.113] parse error at byte 13: syntax error while parsing CBOR string: expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0xB4", json::parse_error&);
|
||||
}
|
||||
|
||||
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
|
||||
|
||||
Reference in New Issue
Block a user