-
Notifications
You must be signed in to change notification settings - Fork 152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flatten Out an unordered_map in a Struct #1627
Comments
Glaze currently doesn't have a clean solution for merging during reads for dynamic types. This is tricky to do in a generic way because it means combining two separate hashing systems for efficiency. The solution I typically take for these cases is to utilize Consider this solution: #include <iostream>
#include "glaze/glaze.hpp"
using map_t = std::unordered_map<std::string_view, std::string_view>;
struct Feature {
map_t attributes{};
std::optional<map_t> errors{};
};
namespace glz {
template <>
struct detail::to<JSON, Feature> {
template <auto Opts, class Value>
static void op(Value&& value, auto&& ctx, auto&& b, auto&& ix) {
if (value.errors) {
auto merged = glz::merge{value.attributes,
glz::obj{"errors", value.errors.value()}};
detail::write<JSON>::template op<Opts>(merged, ctx, b, ix);
} else {
detail::write<JSON>::template op<Opts>(value.attributes, ctx, b,
ix);
}
}
};
} // namespace glz
int main() {
Feature obj{.attributes = {{"a", "1"}, {"b", "2"}, {"c", "3"}},
.errors = map_t{{"x", "y"}, {"w", "z"}}};
auto buffer = glz::write_json(obj).value_or("error");
std::cout << buffer << '\n';
std::unordered_map<std::string_view, glz::raw_json_view> input;
auto ec = glz::read_json(input, buffer);
if (ec) {
std::cerr << glz::format_error(ec, buffer) << '\n';
}
if (input.contains("errors")) {
ec = glz::read_json(obj.errors, input["errors"].str);
if (ec) {
std::cerr << glz::format_error(ec, input["errors"].str) << '\n';
}
// errors have now been populated
if (obj.errors) {
std::cout << "Errors:\n";
for (auto& [key, value] : obj.errors.value()) {
std::cout << key << ", " << value << '\n';
}
}
}
return 0;
} Note that I added custom serialization for
Making custom |
Here's a compiler explorer link to the example: https://gcc.godbolt.org/z/K9KGbnh35 |
Thanks for the details and the example! std::unordered_map<std::string_view, glz::raw_json_view> input;
auto ec = glz::read_json(input, buffer);
if (ec) {
std::cerr << glz::format_error(ec, buffer) << '\n';
}
for (auto& [key, value] : input) {
std::cout << key << ", " << value.str << '\n';
} a, "1"
b, "2"
c, "3" Is there a way to get around that? |
Yes, you're delaying your parse for the raw_json values. So, you need to do a read_json call to decode these values (and remove quotes in the case of strings). This does mean you are doing two passes on the input buffer, but the first is just skipping the value and quite fast. |
Hi,
I have a C++ application which is sending&receiving json messages that have the following structure
For example:
I tried creating a struct like the following:
However, this will result in a key "attributes" capturing all the key/value pairs, which is not what I want:
I also tried using glz::merge:
Which does write the json structure I want, but then I'm not sure I should read such message
Is there a way to get around this?
Thanks!
The text was updated successfully, but these errors were encountered: