1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
#include <iostream>
#include "glaze/glaze.hpp"
namespace mylib
{
enum struct MyEnum { First, Second };
enum struct MyFlag { Yes, No };
} // namespace mylib
namespace glz
{
template <>
struct meta<mylib::MyEnum>
{
using enum mylib::MyEnum;
static constexpr auto value = enumerate(First, Second);
};
template <>
struct meta<mylib::MyFlag>
{
using enum mylib::MyFlag;
static constexpr auto value = enumerate(Yes, No);
};
} // namespace glz
// Test struct using automatic reflection
namespace test1
{
struct AppContext
{
int num{};
mylib::MyEnum e{};
mylib::MyFlag f{};
};
} // namespace test1
// Use indexed rename_key to automatically use enum type names as keys
template <>
struct glz::meta<test1::AppContext>
{
template <size_t Index>
static constexpr auto rename_key()
{
// Get the member type at this index
using MemberType = glz::member_type_t<test1::AppContext, Index>;
// If it's an enum, use the type name; otherwise use the member name
if constexpr (std::is_enum_v<MemberType>) {
return glz::name_v<MemberType>;
}
else {
return glz::member_nameof<Index, test1::AppContext>;
}
}
};
// Test with custom short names (strip namespace)
namespace test2
{
struct AppContext
{
int num{};
mylib::MyEnum e{};
mylib::MyFlag f{};
};
} // namespace test2
template <>
struct glz::meta<test2::AppContext>
{
template <size_t Index>
static constexpr auto rename_key()
{
using MemberType = glz::member_type_t<test2::AppContext, Index>;
if constexpr (std::is_enum_v<MemberType>) {
// Strip namespace from enum type name
constexpr auto full_name = glz::name_v<MemberType>;
constexpr size_t pos = full_name.rfind("::");
return (pos == std::string_view::npos) ? full_name : full_name.substr(pos + 2);
}
else {
return glz::member_nameof<Index, test2::AppContext>;
}
}
};
// Test that it works with non-enum types too
namespace test3
{
struct Point
{
double x{};
double y{};
};
} // namespace test3
// Transform all keys to uppercase
template <>
struct glz::meta<test3::Point>
{
template <size_t Index>
static constexpr auto rename_key()
{
constexpr auto name = glz::member_nameof<Index, test3::Point>;
if constexpr (name == "x")
return "X";
else if constexpr (name == "y")
return "Y";
else
return name;
}
};
int main()
{
std::cout << "=== Test 1: Enum type names (full) ===\n";
test1::AppContext obj1{42, mylib::MyEnum::Second, mylib::MyFlag::Yes};
std::string json1 = glz::write_json(obj1).value_or("error");
std::cout << json1 << '\n';
bool test1_pass = (json1 == R"({"num":42,"mylib::MyEnum":"Second","mylib::MyFlag":"Yes"})");
std::cout << (test1_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";
std::cout << "=== Test 2: Enum type names (short) ===\n";
test2::AppContext obj2{42, mylib::MyEnum::Second, mylib::MyFlag::Yes};
std::string json2 = glz::write_json(obj2).value_or("error");
std::cout << json2 << '\n';
bool test2_pass = (json2 == R"({"num":42,"MyEnum":"Second","MyFlag":"Yes"})");
std::cout << (test2_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";
std::cout << "=== Test 3: Generic key transformation ===\n";
test3::Point obj3{3.14, 2.71};
std::string json3 = glz::write_json(obj3).value_or("error");
std::cout << json3 << '\n';
bool test3_pass = (json3 == R"({"X":3.14,"Y":2.71})");
std::cout << (test3_pass ? "✓ PASS" : "✗ FAIL") << "\n\n";
if (test1_pass && test2_pass && test3_pass) {
std::cout << "All tests passed!\n";
return 0;
}
else {
std::cout << "Some tests failed!\n";
return 1;
}
}
|