Closed laurentcau closed 3 months ago
@laurentcau , you are on the right track.
But that won't compile because of restrictions C++ imposes on you...
struct GenericJSon : public std::map<std::string, std::variant<Value, std::vector<Value>, GenericJSon>>
A struct cannot inherit from itself. However, a struct can contain a pointer to itself:
https://github.com/getml/reflect-cpp/blob/main/docs/rfl_ref.md
And then you could define a ReflectionType
, like this:
https://github.com/getml/reflect-cpp/blob/main/docs/custom_classes.md
I have actually been thinking about whether we should support something like this out-of-the-box, but so far it really hasn't been a top priority. But now that you have asked for it, I will think about it.
struct GenericJSon : public std::map<std::string, std::variant<Value, std::vector<Value>, GenericJSon>>
is valid c++. I have no problem to define and instantiate such object on VS2022. The issue is more in the rfl::json::read call that tries to count the number of fields that is infinite:
1>E:\build\unreal\external\include\rfl\internal\num_fields.hpp(145,24): error C2607: static assertion failed
1>(compiling source file '../../../../repos/eon/UnrealSandbox/Public/SDK/Core/Json/JsonTest.cpp')
1>E:\build\unreal\external\include\rfl\internal\num_fields.hpp(150,62):
1>while evaluating consteval function 'rfl::internal::CountFieldsHelper<T>::get_nested_base_field_count'
1> with
1> [
1> T=GenericJSon
1> ]
1>E:\build\unreal\external\include\rfl\internal\num_fields.hpp(150,62):
1>while evaluating consteval function 'rfl::internal::CountFieldsHelper<T>::get_nested_base_field_count'
1> with
1> [
1> T=GenericJSon
1> ]
1>E:\build\unreal\external\include\rfl\internal\num_fields.hpp(150,62):
....
@laurentcau , here is an untested first draft:
#ifndef RFL_GENERIC_HPP_
#define RFL_GENERIC_HPP_
#include <map>
#include <string>
#include <variant>
#include <vector>
#include "rfl.hpp"
class Generic {
public:
using ReflectionType = std::variant<bool, double, int, std::string,
std::vector<rfl::Ref<Generic>>,
std::map<std::string, rfl::Ref<Generic>>>;
Generic(const ReflectionType& _value) : value_(_value) {}
~Generic() = default;
ReflectionType reflection() const { return value_; };
private:
ReflectionType value_;
};
#endif
Feel free to improve it and then open a PR with this as a new library feature.
@liuzicheng1987 It works well. A small improvement: the extra rfl::Ref is in fact not needed. It works well without (and remove extra pointer dereference when you want to retrieve the data). (We can also use unordered_map.) So
using ReflectionType = std::variant<bool, int, double, std::string,
std::vector<Generic>,
std::unordered_map<std::string, Generic>>;
is working fine on my side. Thanks!
also, you need to declare "int" before "double" to make "int" detection work.
@laurentcau, these are both good points.
This is just a first draft that I hacked into my keyboard within a minute or so.
Again, if you want to turn this into something more user-friendly and add it as an actual library feature, I would love to have it! Absolutely feel free to open a PR.
Hi, I thought it was possible to use a generic way to load json (like a DOM) with your library. But it doesn't seem to be as simple as I thought. I tried something like that:
It partially works without recursive definition (GenericJSon) but it fails to compile with it. Do you know how to fix this or do you have other idea to achieve this?