mirror of
https://github.com/nlohmann/json.git
synced 2026-07-09 12:05:10 +00:00
Document std::optional<T> direct-init/copy-init limitation with null
Add regression test pinning current behavior (CHECK_THROWS_AS) in the null section of unit-conversions.cpp with detailed comment explaining the C++ language-level cause (std::optional's own converting constructor wins overload resolution over basic_json::operator T()). Add a warning callout in conversions.md documenting that direct construction/ assignment of std::optional<T> from JSON null throws type_error 302, with a clear workaround (use get<std::optional<T>>() or get_to() instead, which correctly produce std::nullopt). This is a limitation at the language level: there is no SFINAE path to distinguish "called from inside std::optional's own constructor" from "direct call", so fixing it would require breaking changes to operator ValueType(). A permanent fix belongs in the 4.0 type-strictness redesign (#3453). Signed-off-by: Niels Lohmann <mail@nlohmann.me> Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -66,6 +66,24 @@ which forces the explicit `get` form and can catch unintended conversions at com
|
||||
floating-point value as an integer truncates it, and narrowing conversions may overflow. See
|
||||
[number conversion](types/number_handling.md#number-conversion) for details and how to guard against it.
|
||||
|
||||
!!! warning "std::optional direct construction from JSON null throws"
|
||||
|
||||
Constructing or assigning `std::optional<T>` directly from a JSON value does not correctly produce
|
||||
`std::nullopt` for a JSON `null`:
|
||||
|
||||
```cpp
|
||||
json j_null;
|
||||
std::optional<std::string> opt = j_null; // ❌ throws type_error 302
|
||||
```
|
||||
|
||||
This is due to C++ language rules: `std::optional<T>` has its own converting constructor that is chosen over
|
||||
`basic_json::operator T()` when both are viable. Use `get<std::optional<T>>()` or `get_to()` instead:
|
||||
|
||||
```cpp
|
||||
auto opt = j_null.get<std::optional<std::string>>(); // ✅ std::nullopt
|
||||
j_null.get_to(opt); // ✅ std::nullopt
|
||||
```
|
||||
|
||||
## Putting values in
|
||||
|
||||
The reverse direction works the same way: assigning or constructing a `json` from a C++ value converts it to JSON.
|
||||
|
||||
Reference in New Issue
Block a user