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
821 stars 65 forks source link

std::wstring support & modifing existing field types #60

Closed Lazrius closed 5 months ago

Lazrius commented 5 months ago

Hello! I have been converting a project that previously used nlohmann::json and its serialization to use this project. It's mostly been okay, but I've noticed there is no support for std::wstring. I know that wstrings are often a pain, so this isn't too unexpected, but previously, with nlohmann, there was a way to extend the parser to support wstring types by instructing the parser to automatically convert them to std::string.

Example:

namespace nlohmann
{
    template <>
    struct adl_serializer<std::wstring>
    {
            static void to_json(json& j, const std::wstring& str) { j = StringUtils::wstos(str); }

            static void from_json(const json& j, std::wstring& str) { str = StringUtils::stows(j.get<std::string>()); }
    };
}

In that example, we simply do the conversion from std::string to std::string and visa versa. I noticed while trawling through the docs that we can extend types in reflect-cpp by doing something similar:

namespace rfl {
namespace parsing {

template <class ReaderType, class WriterType>
struct Parser<ReaderType, WriterType, Person>
    : public CustomParser<ReaderType, WriterType, Person, PersonImpl> {};

}
} 

The main problem that I can see here, is that in the example of a string, if we setup a custom struct that mirrors a string and do the conversion, it's not going to transform it into a string correctly, but rather into a struct/object that has the internal fields and whatnot.

Is there a way to properly handle structs that have std::wstrings or other unsupported 'primative' types?

liuzicheng1987 commented 5 months ago

@Lazrius , I think we could just add another parser.

We would basically have to implement a Parser_wstring.hpp that implements the transformation from wstring to string and vice versa.

https://github.com/getml/reflect-cpp/tree/main/include/rfl/parsing

If you want to do it, a PR is welcome. Otherwise you can just lay out how the transformation from and to wstring is supposed to behave and I’ll implement it.

Lazrius commented 5 months ago

Awesome. I will look into doing a PR, but the main issue with std::wstring (as I understand it) is that the implementation of it is different depending on OS. I believe that on Windows it represents a UTF-16 string, but represents a UTF-32 string on Linux. No idea what wchar_t is set to on MacOS.

I'll take a look!

liuzicheng1987 commented 5 months ago

@Lazrius if you have any questions, don’t hesitate to ask. I will help you wherever I can.

Lazrius commented 5 months ago

@liuzicheng1987 I have opened up a PR (#61) - let me know if this was the proper way to do it and all that, happy to make changes if needed.

liuzicheng1987 commented 5 months ago

Merged