nlohmann/json

Error converting to/from scoped enumerations

askr0x123456789 opened this issue · 3 comments

Description

nlohmann::json conversion from invalid json to scoped enumeration works without exceptions.

Reproduction steps

1- define a scoped enumeration
2- use NLOHMANN_JSON_SERIALIZE_ENUM for convertion from string to the enum type
3- convert an invalid string to the enum type

Expected vs. actual results

Actual results:

color: "blue"
color (int): 0
color is red
color (int): 0

Minimal code example

enum class Color: int {
    Red,
    Green,
    Blue
};

NLOHMANN_JSON_SERIALIZE_ENUM(Color, {
    {Color::Red, "red"},
    {Color::Green, "green"},
    {Color::Blue, "blue"}
});

int main() {
    auto blue = Color::Blue;
    const nlohmann::json blueJson = blue;
    fmt::println("color: {}", blueJson.dump()); // correct - works fine for valid enumerations
    const nlohmann::json invalidColorJson = "yellow";
    const Color invalidColor = invalidColorJson.get<Color>();
    fmt::println("color (int): {}", static_cast<int>(invalidColor)); // output is 0 - which is wrong
    if (invalidColor == Color::Red) { /// condition is true, which is wrong
        fmt::println("color is red");
    }
    fmt::println("color (int): {}", static_cast<int>(Color::Red)); // output is 0 - correct
    return EXIT_SUCCESS;
}

Error messages

No error message

Compiler and operating system

g++-14 on Kali Linux 2024.3

Library version

latest from develop branch

Validation

You try to find an enum value for the string "yellow". The documentation states:

When using template get<ENUM_TYPE>(), undefined JSON values will default to the first specified conversion. Select this default pair carefully. See example 1 below.

Therefore, Color::Red is returned.

Unless I misunderstood the issue, I would say that the library behaves as documented.

Shouldn't the correct behavior be throwing an exception?

I'm reading millions of records from a database and the available string value might be wrong.
If I'm not sure about the string values, converting a string to enum, is better be done by if statements.

I understand. The current macro behaves as documented, and changing it would break existing code. One possibility would be adding a throwing version of the macro.