getml / reflect-cpp

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML / msgpack.org[C++20]
https://getml.github.io/reflect-cpp/
MIT License
901 stars 76 forks source link

potentially simpler way to do custom parsing #141

Closed BjornSAIM closed 1 month ago

BjornSAIM commented 1 month ago

Currently you have to define a new aggregate type and a parser specialization to achieve this. After fiddling around for a bit I was able to get this alternative to work using concepts:

// defined in the library
template <T>
struct Reflector;

// defined by the user
template <>
struct Reflector<Vector3> {
    struct refl_type {
        float x = {}, y = {}, z = {};
    };
    static constexpr Vector3 to(const refl_type& v) noexcept
    {
        return { v.x, v.y, v.z };
    }

    static constexpr refl_type from(const Vector3& v)
    {
        return { v.x, v.y, v.z };
    }
};

It's conceptually similar to what is happening now, but to me this seems more straightforward, it feels a bit like implementing a serialize function pair. Ofcourse that's just my opinion though.

I also had a question. Is it expected behavior that the library can't handle structs that have all public fields but explicitly defined constructors?

liuzicheng1987 commented 1 month ago

@BjornSAIM, this seems great, I would like to see how it is implemented, though. Does it work for formats other than JSON? How do you handle processors? Could you share the code or maybe open a PR that we could discuss further?

As for your question…it’s not really intended behaviour, it’s more of a necessary evil. It’s also documented, refer to the very bottom of this page:

https://github.com/getml/reflect-cpp/blob/main/docs/structs.md

liuzicheng1987 commented 1 month ago

@BjornSAIM after giving it some more thought, I have now figured out how this works. I think it is a great idea. A PR would be very welcome.

BjornSAIM commented 1 month ago

@BjornSAIM, this seems great, I would like to see how it is implemented, though. Does it work for formats other than JSON? How do you handle processors? Could you share the code or maybe open a PR that we could discuss further?

As for your question…it’s not really intended behaviour, it’s more of a necessary evil. It’s also documented, refer to the very bottom of this page:

https://github.com/getml/reflect-cpp/blob/main/docs/structs.md

That's what I expected, but in a case like this:

struct Vector3 {
    float x = {}, y = {} ,z = {};
    constexpr Vector3() = default;
    constexpr Vector3(float x, float y, float z)
        : x(x), y(y), z(z)
    {
    }
...
};

I would expect this to match the criterium. I think it might be possible to soften the constrain from std::is_aggregate_v to is constructible in this way using concepts.

I will setup a PR somewhere this weekend. I also fixed a bunch of obnoxious warnings. Do you want those as well (and if yes, separate or same pr?). EDIT: Ok, I think I understand why it's not quite this simple, anyway, i'll stick to the custom parser approach for these cases.

liuzicheng1987 commented 1 month ago

Sure, separate PR, please as these are two different topics. Thank you so much.

liuzicheng1987 commented 1 month ago

Resolved (https://github.com/getml/reflect-cpp/commit/6dadbc2506fa80d61a67ca03458a9671a2556d30)