Mapping with varying data types #435
-
Hello, I'm currently working on a project that involves mapping JSON data to class/struct members. However, I've come across a few scenarios where the data types in my classes/structs don't always match the JSON structure. Instead of creating multiple classes/structs for different JSON layouts, I'm attempting to consolidate them into one structure. I've written some example code to illustrate what I'm trying to achieve. If it's not currently possible to accomplish this, I would greatly appreciate any ideas or suggestions for a clean alternative approach. Additionally, I'm curious if there's potential for this feature to be added in the future. Thanks in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 4 replies
-
Mapping a quoted number to an integer is simple. To parse template <>
struct glz::meta<Person> {
using T = Person;
static constexpr auto value = glz::object("age", quoted<&T::age>());
}; Mapping the date_of_birth is a little more complex: struct Person {
std::string name{};
int age{};
std::string city{};
std::string residence{};
void getAge(const std::string birthdateStr) {
std::tm birthdate = {};
std::istringstream ss(birthdateStr);
ss >> std::get_time(&birthdate, "%d/%m/%Y");
if (ss.fail()) {
std::cout << "Failed to parse birthdate: " << birthdateStr << "\n";
}
const auto birth = std::chrono::system_clock::from_time_t(std::mktime(&birthdate));
const auto age_seconds = std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - birth);
age = static_cast<int>(age_seconds.count()) / (60 * 60 * 24 * 365);
}
};
template <>
struct glz::meta<Person> {
using T = Person;
static constexpr auto value =
glz::object(
"name", &T::name, "full_name", &T::name,
"age", &T::age, "years_old", &T::age, "date_of_birth", invoke<&T::getAge>(),
"city", &T::city, "residence", &T::residence
);
};
suite function_call = [] {
"function_call"_test = [] {
Person obj{};
std::string s = R"({
"full_name": "Brian Smith",
"date_of_birth": ["01/01/1990"],
"residence": "San Francisco"
})";
expect(!glz::read_json(obj, s));
expect(obj.age == 33);
};
}; Note that getAge needs to be a member function with a void return. You could also use a std::function and capture Let me know your thoughts! |
Beta Was this translation helpful? Give feedback.
-
That is what I did end up using, thanks
Very nice, I'll see how I can make use of that. Anyway, I shall close this discussion as solved now and here is the full implementation of what I ended up doing - JsonMeta.hpp Thanks for all of your help! |
Beta Was this translation helpful? Give feedback.
I'll just note that if you can use
std::variant<std::string, int>
, this is also supported in glaze.