qicosmos/iguana

REFLECTION 不支持添加std::variant<>类型的字段反射

chinajia opened this issue · 12 comments

struct nest {
std::string name;
my_space::my_struct value;
std::variant<int, std::string> var;
bool operator==(const nest &o) const {
return name == o.name && value == o.value;
}
};

void example2() {
std::variant<int,std::string> var;
var = 1;
nest v{"Hi", {1, 2, 3},var}, v2;
std::string s;
iguana::to_json(v, s);
std::cout << s << std::endl;
iguana::from_json(v2, s);
CHECK(v == v2);
};

iguana::to_json(v, s);这行报错,编译器无法正确调用std::variant<>类型的重载函数

这几天看一下这个问题。

iguana::from_json(v2, s); 是这一行报错。tojson没有问题。

from_json 漏掉了代码,稍后等PR 合并之后你再拉master 代码测试一下吧。

struct nest1 {
std::string name;
my_space::my_struct value;
std::variant<int, std::string, std::vector, client::person> var;
bool operator==(const nest1& o) const {
return name == o.name && value == o.value;
}
};

REFLECTION(nest1, name, value, var);

void example2() {
std::variant<int, std::string, std::vector, client::person> var;
client::person p;
p.age = 20;
p.name = "jack";
var = p;
nest1 v{"Hi", {1, 2, 3}, var}, v2;
std::string s;
iguana::to_json(v, s);
std::cout << s << std::endl;
iguana::from_json(v2, s);
assert(v == v2);
}

你好,我在std::variant中多添加了person结构体,然后var使用person结构体赋值,代码如上。
编译可以正常,运行的时候tojson可以正常序列化,然后fromjson会出现运行异常。

请问这是什么原因?望回复,感谢!

这个测试代码不完整吧,vector里面是啥,person的定义啥的呢?

不好意思,贴的代码有问题,我重新贴下:
namespace client {
struct person {
std::string name;
int64_t age;
};

REFLECTION(person, name, age);
} // namespace client

struct nest1 {
std::string name;
my_space::my_struct value;
std::variant<int, std::string, client::person> var;
bool operator==(const nest1& o) const {
return name == o.name && value == o.value;
}
};

REFLECTION(nest1, name, value, var);

void example2() {
std::variant<int, std::string, client::person> var;
client::person p;
p.age = 20;
p.name = "jack";
var = p;
nest1 v{"Hi", {1, 2, 3}, var}, v2;
std::string s;
iguana::to_json(v, s);
std::cout << s << std::endl;
iguana::from_json(v2, s);
assert(v == v2);
}

您再看下,我把vector删了,person就是example_json例子里面的结构体。

提了一个pr 修复反序列化variant类型。
不过还是尽量不用variant类型为好,反序列化的效率比较低,会尝试多次反序列化variant中可能的类型,直到成功为止,最坏的情况需要尝试variant_size_v - 1 次。

谢谢答复。那确实类型多了,效率就低。但是我这样需求:数据格式为{"seq":1, "type":"login", "data":{...}},其中data会根据type类型不同,会是不同json类型,可能是对象,可能是数组,可能是整形等。

我是想到使用variant 变量来定义data这个json字段,从而实现需求。是否还有其他效率高的方法可以实现呢?

代码已经合并了,反序列化支持了variant。

也许可以分成两部分,把data单独分开,data就用具体的类型,前面的部分增加一个data_type 字段。后面先解析data type,然后再根据其类型去解析具体的data。

不过可以先试试variant 效率怎么样,说不定也能满足你的需求。

代码已经合并了,反序列化支持了variant。

也许可以分成两部分,把data单独分开,data就用具体的类型,前面的部分增加一个data_type 字段。后面先解析data type,然后再根据其类型去解析具体的data。

我们没太明白这个思路,针对这个示例{"seq":1, "type":"login", "data":{...}},你的意思是先定义一个结构体 struct header{int seq, string type},然后先反序列化为header,再根据type使用具体类型:比如struct login{int seq, string type, 具体data},再反序列化一次吗?

不是,是分成两个结构体,一个是header,一个是data,先反序列化header,再根据header 反序列化data。