diff --git a/docs/mkdocs/docs/api/basic_json/basic_json.md b/docs/mkdocs/docs/api/basic_json/basic_json.md index 83c50007e..07f3ae066 100644 --- a/docs/mkdocs/docs/api/basic_json/basic_json.md +++ b/docs/mkdocs/docs/api/basic_json/basic_json.md @@ -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 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 `#!cpp true` (default), the type of the JSON value to be created is deducted from the initializer list `init` @@ -146,6 +152,11 @@ basic_json(basic_json&& other) noexcept; - `BasicJsonType` is a `basic_json` type. - `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`: : `uncvref_t` diff --git a/docs/mkdocs/docs/api/basic_json/object_t.md b/docs/mkdocs/docs/api/basic_json/object_t.md index 7dda42d2b..cf0ffc87b 100644 --- a/docs/mkdocs/docs/api/basic_json/object_t.md +++ b/docs/mkdocs/docs/api/basic_json/object_t.md @@ -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 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 ??? example diff --git a/docs/mkdocs/docs/api/basic_json/string_t.md b/docs/mkdocs/docs/api/basic_json/string_t.md index dc85fcd4d..78ef4ff45 100644 --- a/docs/mkdocs/docs/api/basic_json/string_t.md +++ b/docs/mkdocs/docs/api/basic_json/string_t.md @@ -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_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 ??? example diff --git a/tests/src/unit-alt-string.cpp b/tests/src/unit-alt-string.cpp index 9c04afa4a..46e062c6e 100644 --- a/tests/src/unit-alt-string.cpp +++ b/tests/src/unit-alt-string.cpp @@ -322,14 +322,12 @@ TEST_CASE("alternative string type") SECTION("JSON pointer") { - // conversion from json to alt_json fails to compile (see #3425); - // attempted fix(*) produces: [[['b','a','r'],['b','a','z']]] (with each char being an integer) - // (*) disable implicit conversion for json_refs of any basic_json type - // alt_json j = R"( - // { - // "foo": ["bar", "baz"] - // } - // )"_json; + // Direct conversion from a json literal to alt_json is not supported due to issue #3425: + // alt_json's string_t (alt_string) is not directly constructible from std::string, so the + // cross-basic_json conversion falls back to the array-conversion path, incorrectly representing + // objects as arrays of [key, value] pairs and strings as arrays of character codes. + // See https://github.com/nlohmann/json/issues/3425 for details. + // Workaround: use alt_json::parse() instead of implicit conversion. auto j = alt_json::parse(R"({"foo": ["bar", "baz"]})"); CHECK(j.at(alt_json::json_pointer("/foo/0")) == j["foo"][0]);