Comments (9)
Your single lambda approach invokes the function for both reading and writing. To split out different behaviors for reading and writing with lambdas you can register separate lambdas using glz::custom
.
A basic example:
struct custom_load_t
{
std::vector<int> x{};
std::vector<int> y{};
struct glaze
{
static constexpr auto read_x = [](auto& s) -> auto& { return s.x; };
static constexpr auto write_x = [](auto& s) -> auto& { return s.y; };
static constexpr auto value = glz::object("x", glz::custom<read_x, write_x>);
};
};
from glaze.
You probably have a good reason for using unions, but Glaze also has a lot of support for std::variant that can achieve similar goals: docs/variant-handling.md
from glaze.
The problem is that I don't think C++ has a mechanism to determine the alternative types of a union. Whereas, with a std::variant we can look at the types at compile time and build logic about how to serialize/deserialize it.
In the glz::meta
we could have the user list the union types. This requires more typing, but I think makes sense.
I do think it would be useful to add union support to Glaze (for trivial types). I'll update this issue's name appropriately.
from glaze.
Thanks for the quick response! This looks like what I'm going for and I'll give it a try.
In the meantime I came up with another solution where I define a "normalizing" struct to act as a shim for reading/writing data that just uses the glz::meta
approach with normal reflection
template <>
struct glz::meta<normalized_data>
{
using T = normalized_data;
static constexpr auto value = object(
"actor-name" , &T::actor_name
"actor-type" , &T::actor_type
)
}
struct normalized_data
{
string actor_name
string actor_type
}
struct Data
{
union u1
int unionType
}
void serialize(Data &data)
{
normalized_data.field1 = transformUnion(data.u1, data.unionType)
glz::write(normalized_data, buffer)
}
I'll weigh the two options if I ever need to add new structs, and if I ever move to variants I'll give that a second look.
One last question (slightly related), my glz::meta seems to output the incorrect key (just uses member name for reflection rather than how I specified it). Is there an option needed in order to enable dasherized/hyphenated key names? Below is the output
{"actor_name":"John Smith","actor_type":"developer"}
from glaze.
Cool, that sounds good. And, std::variant is really nice if you get around to experimenting with it.
One last question (slightly related), my glz::meta seems to output the incorrect key (just uses member name for reflection rather than how I specified it). Is there an option needed in order to enable dasherized/hyphenated key names? Below is the output
This issue is something I haven't seen before. Maybe your glz::meta
specialization needs to be declared after your class, or it isn't in the same translation unit as your serialization. If you could provide me with a simple example of code that produces the incorrect output that would help me find the problem.
from glaze.
No problem. I think it's what you're saying, I changed the names entirely and they don't seem to have any effect.
This should be a working example (I added a bit more of my actual code to illustrate what's happening):
glazeMetadata.h
#include "Reflection.h"
#include <glaze/glaze.hpp>
namespace glz {
template <>
struct meta<event::Data>
{
using T = event::Data;
static constexpr auto value = object(
"actor-name" , &T::actor_name
, "actor-type" , &T::actor_type
, "job-id" , &T::job_id
);
};
} // namespace glz
Reflection.h
namespace event
{
struct Data
{
uint32_t job_id;
std::string actor_name;
std::string actor_type;
};
} // namespace event
These two structs are in separate header files inside of the same library, built using CMake. Here's my test code:
event::Data data{};
data.job_id = 1;
data.actor_name = "John Smith";
data.actor_type = "developer";
std::string_view buffer;
glz::write_json(data, buffer);
from glaze.
No need to chase this down, it was the include order that was throwing things off. I fixed it by just moving the meta specialization into the same header.
Appreciate all the help!
from glaze.
Sorry to reopen this, but kind of ran into trouble with this approach further down the line, but it seems like there isn't a way to access the data read from the json string inside my lambda:
template<>
struct glz::meta<Data>
{
static constexpr auto read_type = [](const auto &s) {
return // how do I get the raw string value read from JSON here in order to transform it back into my struct field?
};
static constexpr auto write_type = [](const auto& s) {
return printTypeString(s.type));
};
static constexpr auto value = object( "type" , glz::custom<read_type, write_type>)
}
When I run this code all I get in the lambda is the empty struct Im trying to read into. I guess the real thing I'm after here is full control over how data gets written/read from json based on access to both the struct we're reading into, and the raw json data. Is there a way to pass more arguments to custom readers and writers than just const auto&
?
something like:
static constexpr auto read_type = [](const auto &s) {
string tmp = glz::read("type")
return toType(tmp); // how do I get the raw string value read from JSON here in order to transform it back into my struct field?
};
from glaze.
I think I see how to do this now based on the compile error messages
static constexpr auto const read_instrument_type = [](Data&s, const std::string_view& value) -> void {
s.type = serialize::FieldHelper::parseInstrumentTypeString(value);
};
static constexpr auto write_instrument_type = [](const auto& s) {
return printType(type);
};
It still doesn't eliminate the need for tagged union support (I'd imagine it'd be very similar to the variant support) We do have strong reasons for wanting to control the size of the union but if we ever make the change it should work for our purposes. Are there any plans to support tagged unions? e.g.
union typeUnion
{
type1 cool
type2 beans
}
enum type;
I started down my own workaround to imitate what you do for variant, but it seems there's no support for union:
template<>
struct meta<typeUnion>
{
using T = typeUnion;
static constexpr std::string_view tag = "type";
static constexpr auto ids = std::array{"type1Tag", "type2Tag};
};
/Serializer.h:82:26: error: no matching function for call to ‘read_json(typeUnion&, std::string_view&)’
82 | errc = glz::read_json(m_union, buffer);
| ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~
In file included from /home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/json/json_ptr.hpp:13,
from /home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/binary/write.hpp:11,
from /home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/binary/ptr.hpp:7,
from /home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/binary.hpp:7,
from /home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/glaze.hpp:35,
from Reflection.h:8,
from Serializer.h:4,
from SerializerTest.cpp:9:
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/json/read.hpp:2709:37: note: candidate: ‘template<class T, class Buffer> requires read_json_supported<T> glz::parse_error glz::read_json(T&, Buffer&&)’
2709 | [[nodiscard]] inline parse_error read_json(T& value, Buffer&& buffer) noexcept
| ^~~~~~~~~
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/json/read.hpp:2709:37: note: template argument deduction/substitution failed:
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/json/read.hpp:2709:37: note: constraints not satisfied
...
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/core/opts.hpp:223:12: required for the satisfaction of ‘read_json_supported<T>’ [with T = typeUnion]
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/core/opts.hpp:223:34: in requirements [with T = typeUnion]
/home/user/.cache/CPM/glaze/2c5e2f53ecc3ddc14bae077f3e1c198222641b8e/include/glaze/core/opts.hpp:223:53: note: the required expression ‘glz::detail::from_json<typename std::remove_cvref<_Tp>::type>{}’ is invalid
223 | concept read_json_supported = requires { detail::from_json<std::remove_cvref_t<T>>{}; };
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from glaze.
Related Issues (20)
- std::pair arrays roundtrip
- `float` member issue with `clang++-15` and `g++-12` HOT 3
- `json_test.cpp(7840): warning C4267: '=': conversion from 'size_t' to 'uint16_t', possible loss of data` HOT 1
- glz::reader/glz::writer for incremental reading/writing HOT 5
- Partial read for BEVE
- glz::raw without quotes question HOT 1
- Binary serialization of hidden members HOT 2
- error: constructor priorities are not supported 3316 | const char* argv[]) HOT 3
- gcc and msvc compilation error with explicit constructors HOT 19
- Warnings & Errors in various configurations HOT 16
- rapidjson 对比 HOT 15
- How do I read an array of json objects in glaze? HOT 15
- field-based parse bifurcation HOT 1
- Add the library to nuget HOT 2
- Option to skip reading in null values
- calculate serialize size before serialization and serialize to pre-allocated memory HOT 4
- Option to use partial with char* or char[] HOT 3
- data_must_be_null_terminated issue HOT 1
- Bug: Malformed JSON string produced HOT 11
- Build and test for 32-bit in Actions
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from glaze.