mirror of
https://github.com/nlohmann/json.git
synced 2026-10-08 18:05:19 +00:00
Make cross-string-type basic_json conversion explicit without implicit conversions (#5591)
* Make cross-string-type basic_json conversion explicit without implicit conversions The converting constructor from another basic_json specialization was always implicit, so a value with a different string_t (std::wstring, a string with a custom allocator, ...) silently converted into a temporary, e.g. when passed to a function taking const nlohmann::json&. Such conversions do not produce correct values (#3425), and JSON_USE_IMPLICIT_CONVERSIONS=0 did not catch them. When JSON_USE_IMPLICIT_CONVERSIONS is 0, the constructor is now explicit if the string types differ. Specializations sharing a string type (json and ordered_json, different serializers or object maps) stay implicitly convertible, so the NLOHMANN_DEFINE_TYPE_* macros keep working with nested json members. get<BasicJsonType>() constructs explicitly and works in both modes. Fixes #2649. Signed-off-by: Niels Lohmann <mail@nlohmann.me> * Construct explicitly in get_to() and to_json(std::optional) With JSON_USE_IMPLICIT_CONVERSIONS=0 the conversion from a basic_json with a different string type is now explicit, but two library paths still assigned such a value implicitly and failed to compile inside the library: - get_to() with a basic_json target (the #2175 overload) did `v = *this`, so json(42).get_to(alt_json&) broke although get<alt_json>() works. - to_json(BasicJsonType&, const std::optional<T>&) is constrained on std::is_constructible (which accepts the explicit constructor) but did `j = *opt`, so converting a std::optional<alt_json> into a json broke. Both now construct the value explicitly, as get_impl() already does. Also replace static_cast<bool>(JSON_USE_IMPLICIT_CONVERSIONS) with a comparison: clang-tidy's modernize-use-bool-literals rejected the cast of the integer literal the macro expands to, failing ci_clang_tidy. Signed-off-by: Niels Lohmann <mail@nlohmann.me> --------- Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -59,6 +61,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)
|
||||
@@ -68,3 +89,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.
|
||||
|
||||
Reference in New Issue
Block a user