Glaze has full support std::variant
when writing, and read support when either the type of the underlying JSON is deducible or the current type stored in the variant is the correct type.
Types can be auto-deduced if the variant contains at most one type matching each of the fundamental JSON types of [string, number, object, array boolean] or multiple object types. std::variant<double, std::string> could be auto deduced but std::variant<double, float> cannot be.
Write example:
std::variant<double, std::string> d = "not_a_fish";
auto s = glz::write_json(d);
expect(s == R"("not_a_fish")");
Read example:
std::variant<int32_t, double> x = 44;
glz::read_json(x, "33");
expect(std::get<int32_t>(x) == 33);
As of glaze 1.0 objects can be auto deduced based on the presence of unique key combinations.
struct xy_t
{
int x{};
int y{};
};
template <>
struct glz::meta<xy_t>
{
using T = xy_t;
static constexpr auto value = object("x", &T::x, "y", &T::y);
};
struct yz_t
{
int y{};
int z{};
};
template <>
struct glz::meta<yz_t>
{
using T = yz_t;
static constexpr auto value = object("y", &T::y, "z", &T::z);
};
struct xz_t
{
int x{};
int z{};
};
template <>
struct glz::meta<xz_t>
{
using T = xz_t;
static constexpr auto value = object("x", &T::x, "z", &T::z);
};
suite metaobject_variant_auto_deduction = [] {
"metaobject_variant_auto_deduction"_test = [] {
std::variant<xy_t, yz_t, xz_t> var{};
std::string b = R"({"y":1,"z":2})";
expect(glz::read_json(var, b) == glz::error_code::none);
expect(std::holds_alternative<yz_t>(var));
expect(std::get<yz_t>(var).y == 1);
expect(std::get<yz_t>(var).z == 2);
b = R"({"x":5,"y":7})";
expect(glz::read_json(var, b) == glz::error_code::none);
expect(std::holds_alternative<xy_t>(var));
expect(std::get<xy_t>(var).x == 5);
expect(std::get<xy_t>(var).y == 7);
b = R"({"z":3,"x":4})";
expect(glz::read_json(var, b) == glz::error_code::none);
expect(std::holds_alternative<xz_t>(var));
expect(std::get<xz_t>(var).z == 3);
expect(std::get<xz_t>(var).x == 4);
};
};
Auto deduction works if the type can be determined by the combination of keys present. If you need to deduce the type based on the value associated with a key you can use the new tagged union support that now allows for custom tags.
struct put_action
{
std::map<std::string, int> data{};
};
template <>
struct glz::meta<put_action>
{
using T = put_action;
static constexpr auto value = object("data", &T::data);
};
struct delete_action
{
std::string data{};
};
template <>
struct glz::meta<delete_action>
{
using T = delete_action;
static constexpr auto value = object("data", &T::data);
};
using tagged_variant = std::variant<put_action, delete_action>;
template <>
struct glz::meta<tagged_variant>
{
static constexpr std::string_view tag = "action";
static constexpr auto ids = std::array{"PUT", "DELETE"}; //Defaults to glz::name_v of the type is ids is not supplied
};
suite tagged_variant_tests = [] {
"tagged_variant_write_tests"_test = [] {
tagged_variant var = delete_action{{"the_internet"}};
std::string s{};
glz::write_json(var, s);
expect(s == R"({"action":"DELETE","data":"the_internet"})");
};
"tagged_variant_read_tests"_test = [] {
tagged_variant var{};
expect(glz::read_json(var, R"({"action":"DELETE","data":"the_internet"})") == glz::error_code::none);
expect(std::get<delete_action>(var).data == "the_internet");
};
};