Skip to content

Instantly share code, notes, and snippets.

@qingfengxia
Last active April 23, 2023 18:11
Show Gist options
  • Select an option

  • Save qingfengxia/92f5fa843ac6bbc951135a32172bfcff to your computer and use it in GitHub Desktop.

Select an option

Save qingfengxia/92f5fa843ac6bbc951135a32172bfcff to your computer and use it in GitHub Desktop.

Revisions

  1. qingfengxia revised this gist Nov 22, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions enum_class_json_conversion.cpp
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,8 @@ NLOHMANN_JSON_SERIALIZE_ENUM expanded to inline functions, so this macro should
    also this macro must be declared within enum type's namespace
    ```
    // include loguru header here, declear enum NamedVerbosity
    // this code injection happen in your project header file, no need to modify loguru.hpp
    namespace loguru
    {
    // this macro must be called in the enum declaring namespace
  2. qingfengxia created this gist Nov 22, 2019.
    119 changes: 119 additions & 0 deletions enum_class_json_conversion.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    /*
    NLOHMANN_JSON_SERIALIZE_ENUM expanded to inline functions, so this macro should be placed in header where enum class is declared
    also this macro must be declared within enum type's namespace
    ```
    namespace loguru
    {
    // this macro must be called in the enum declaring namespace
    NLOHMANN_JSON_SERIALIZE_ENUM(NamedVerbosity, {
    {Verbosity_OFF, "OFF"},
    {Verbosity_FATAL, "FATAL"}, /// program will terminate
    {Verbosity_ERROR, "ERROR"}, /// red text print in console
    {Verbosity_WARNING, "WARNING"}, /// yellow text in console
    {Verbosity_INFO, "INFO"}, /// default 0 for loguru, 20 for python
    {Verbosity_1, "PROGRESS"}, /// 1 for loguru, write into log file
    {Verbosity_2, "DEBUG"}, /// 2 for loguru, write into file
    });
    } // namespace loguru
    ```
    */

    #include "json.hpp"
    #include <assert.h>
    #include <iostream>

    // copy of the NLOHMANN_JSON_SERIALIZE_ENUM here for illustration
    #define JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
    template<typename BasicJsonType> \
    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
    { \
    static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
    static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
    auto it = std::find_if(std::begin(m), std::end(m), \
    [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
    { \
    return ej_pair.first == e; \
    }); \
    j = ((it != std::end(m)) ? it : std::begin(m))->second; \
    } \
    template<typename BasicJsonType> \
    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
    { \
    static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
    static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
    auto it = std::find_if(std::begin(m), std::end(m), \
    [j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
    { \
    return ej_pair.second == j; \
    }); \
    e = ((it != std::end(m)) ? it : std::begin(m))->first; \
    }


    enum class DevicePreference
    {
    CPU, /// item count is small, but processing each item take times
    GPU, /// large items but small job
    };

    // use the official macro
    NLOHMANN_JSON_SERIALIZE_ENUM(DevicePreference, {
    {DevicePreference::CPU, "CPU"},
    {DevicePreference::GPU, "GPU"},
    })

    /* this is the expansion of macro, for debugging, review purpose
    template <typename BasicJsonType> inline void to_json(BasicJsonType& j, const DevicePreference& e)
    {
    static_assert(std::is_enum<DevicePreference>::value, "DevicePreference"
    " must be an enum!");
    static const std::pair<DevicePreference, BasicJsonType> m[] = {
    {DevicePreference::CPU, "CPU"},
    {DevicePreference::GPU, "GPU"},
    };
    auto it = std::find_if(
    std::begin(m), std::end(m),
    [e](const std::pair<DevicePreference, BasicJsonType>& ej_pair) -> bool { return ej_pair.first == e; });
    j = ((it != std::end(m)) ? it : std::begin(m))->second;
    }
    template <typename BasicJsonType> inline void from_json(const BasicJsonType& j, DevicePreference& e)
    {
    static_assert(std::is_enum<DevicePreference>::value, "DevicePreference"
    " must be an enum!");
    static const std::pair<DevicePreference, BasicJsonType> m[] = {
    {DevicePreference::CPU, "CPU"},
    {DevicePreference::GPU, "GPU"},
    };
    auto it = std::find_if(
    std::begin(m), std::end(m),
    [j](const std::pair<DevicePreference, BasicJsonType>& ej_pair) -> bool { return ej_pair.second == j; });
    e = ((it != std::end(m)) ? it : std::begin(m))->first;
    }
    */

    int main()
    {

    // Usage:
    // enum -> json string
    nlohmann::json j = DevicePreference::CPU;
    assert(j == "CPU");
    std::cout << j << std::endl;

    // it is fine to scope enum value by enum type
    DevicePreference ts = DevicePreference::GPU;
    // json string-> enum
    nlohmann::json j3 = "GPU";
    assert( j3.get<DevicePreference>() == DevicePreference::GPU);

    //std::cout << j3.get<DevicePreference>(); // << operator is not supported

    // unmapped json -> enum (default value is first pair)
    nlohmann::json jPi = "unknown";
    assert( jPi.get<DevicePreference>() == DevicePreference::CPU );

    return 0;

    }