Last active
April 23, 2023 18:11
-
-
Save qingfengxia/92f5fa843ac6bbc951135a32172bfcff to your computer and use it in GitHub Desktop.
example code to show c++ enum class to NLOHMANN json conversion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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