Skip to content

Instantly share code, notes, and snippets.

@qingfengxia
Last active April 23, 2023 18:11
Show Gist options
  • Save qingfengxia/92f5fa843ac6bbc951135a32172bfcff to your computer and use it in GitHub Desktop.
Save qingfengxia/92f5fa843ac6bbc951135a32172bfcff to your computer and use it in GitHub Desktop.
example code to show c++ enum class to NLOHMANN json conversion
/*
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
```
// 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
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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment