mirror of
https://github.com/nlohmann/json.git
synced 2026-10-21 05:28:12 +00:00
📝 Document cross-basic_json conversion limitation (#3425)
When converting objects or strings between different basic_json specializations, the target's object_t::key_type or string_t must be directly constructible from the source's corresponding type. If this requirement is not met, the conversion silently falls back to the array-conversion path, producing incorrect results. This documents the limitation and provides references to issue #3425, which tracks this behavior. The comment in unit-alt-string.cpp is clarified to reference the known limitation with a link to the issue, and suggests the parse() workaround. Fixes #3425 (documentation; full fix deferred pending type-trait redesign) Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
4 files changed
+36
-9
No files matched your search
@@ -82,7 +82,13 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
4. This is a constructor for existing `basic_json` types. It does not hijack copy/move constructors, since the parameter
|
4. This is a constructor for existing `basic_json` types. It does not hijack copy/move constructors, since the parameter
|
||||||
has different template arguments than the current ones.
|
has different template arguments than the current ones.
|
||||||
|
|
||||||
The constructor tries to convert the internal `m_value` of the parameter.
|
The constructor tries to convert the internal `m_value` of the parameter. Each member value (object, array, string,
|
||||||
|
etc.) is serialized via the corresponding `to_json()` overload. For objects and strings, the conversion requires
|
||||||
|
that the *target* `basic_json` type's `object_t::key_type` (or `string_t`) be directly constructible from the
|
||||||
|
*source* type's corresponding member type via `is_constructible`. If this requirement is not met, the conversion
|
||||||
|
does not fail to compile; instead, it silently falls back to the array-conversion path, which represents objects
|
||||||
|
as arrays of `[key, value]` pairs and strings as arrays of character codes. This is a known limitation tracked in
|
||||||
|
[issue #3425](https://github.com/nlohmann/json/issues/3425).
|
||||||
|
|
||||||
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
5. Creates a JSON value of type array or object from the passed initializer list `init`. In case `type_deduction` is
|
||||||
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
`#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init`
|
||||||
@@ -147,6 +153,11 @@ basic_json(basic_json&& other) noexcept;
|
|||||||
- `BasicJsonType` is a `basic_json` type.
|
- `BasicJsonType` is a `basic_json` type.
|
||||||
- `BasicJsonType` has different template arguments than `basic_json_t`.
|
- `BasicJsonType` has different template arguments than `basic_json_t`.
|
||||||
|
|
||||||
|
**Note:** For cross-`basic_json` conversions to produce correct results, the target `basic_json`'s
|
||||||
|
`object_t::key_type` and `string_t` must be directly constructible from the source `basic_json`'s
|
||||||
|
corresponding types. See the description of overload (4) above for details on what happens when
|
||||||
|
this requirement is not met.
|
||||||
|
|
||||||
`U`:
|
`U`:
|
||||||
: `uncvref_t<CompatibleType>`
|
: `uncvref_t<CompatibleType>`
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,15 @@ alphabetical order as `std::map` with `std::less` is used by default. Please not
|
|||||||
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
|
[RFC 8259](https://tools.ietf.org/html/rfc8259), because any order implements the specified "unordered" nature of JSON
|
||||||
objects.
|
objects.
|
||||||
|
|
||||||
|
#### Cross-`basic_json` conversion requirements
|
||||||
|
|
||||||
|
When converting an object from one `basic_json` specialization to another via the
|
||||||
|
[converting constructor](basic_json.md#overload-4), the target `object_t`'s `key_type` must be
|
||||||
|
directly constructible from the source `basic_json`'s `string_t` type (or more generally, from the
|
||||||
|
source object's key type). If this requirement is not met, the conversion does not fail; instead,
|
||||||
|
the object is silently converted as an array of key-value pairs, which is incorrect. See
|
||||||
|
[issue #3425](https://github.com/nlohmann/json/issues/3425) for details and an example.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -45,6 +45,15 @@ This implementation is interoperable as it does compare strings code unit by cod
|
|||||||
String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type
|
String values are stored as pointers in a `basic_json` type. That is, for any access to string values, a pointer of type
|
||||||
`string_t*` must be dereferenced.
|
`string_t*` must be dereferenced.
|
||||||
|
|
||||||
|
#### Cross-`basic_json` conversion requirements
|
||||||
|
|
||||||
|
When converting a string value from one `basic_json` specialization to another via the
|
||||||
|
[converting constructor](basic_json.md#overload-4), the target `string_t` must be directly
|
||||||
|
constructible from the source `basic_json`'s `string_t` type. If this requirement is not met, the
|
||||||
|
conversion does not fail; instead, the string is silently converted as an array of character codes,
|
||||||
|
which is incorrect. See [issue #3425](https://github.com/nlohmann/json/issues/3425) for details
|
||||||
|
and an example.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|||||||
@@ -322,14 +322,12 @@ TEST_CASE("alternative string type")
|
|||||||
|
|
||||||
SECTION("JSON pointer")
|
SECTION("JSON pointer")
|
||||||
{
|
{
|
||||||
// conversion from json to alt_json fails to compile (see #3425);
|
// Direct conversion from a json literal to alt_json is not supported due to issue #3425:
|
||||||
// attempted fix(*) produces: [[['b','a','r'],['b','a','z']]] (with each char being an integer)
|
// alt_json's string_t (alt_string) is not directly constructible from std::string, so the
|
||||||
// (*) disable implicit conversion for json_refs of any basic_json type
|
// cross-basic_json conversion falls back to the array-conversion path, incorrectly representing
|
||||||
// alt_json j = R"(
|
// objects as arrays of [key, value] pairs and strings as arrays of character codes.
|
||||||
// {
|
// See https://github.com/nlohmann/json/issues/3425 for details.
|
||||||
// "foo": ["bar", "baz"]
|
// Workaround: use alt_json::parse() instead of implicit conversion.
|
||||||
// }
|
|
||||||
// )"_json;
|
|
||||||
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})");
|
||||||
|
|
||||||
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);
|
||||||
|
|||||||
Reference in new issue
Block a user