qicosmos/iguana

解析集合数据的时候,from_json会产生重复的记录

asing325 opened this issue · 16 comments

#include <assert.h>
void test_v()
{
client::person p1 = { "tom", 20 };
client::person p2 = { "jack", 19 };
client::person p3 = { "mike", 21 };

std::vector<client::person> v{ p1, p2, p3 };
iguana::string_stream ss;
iguana::json::to_json(ss, v);
auto json_str = ss.str();
std::cout << json_str << std::endl;

std::vector<client::person> v1;
iguana::json::from_json(v1, json_str.data(), json_str.length());

assert(v == v1);

// 测试嵌套的数据
client::person allPerson;
allPerson.age = 20 + 19 + 21;
allPerson.name = json_str; // vector<>转换过来的json字符串

ss.clear();
iguana::json::to_json(ss, allPerson);
json_str = ss.str();
std::cout << json_str << std::endl;

client::person allPerson2;
iguana::json::from_json(allPerson2, json_str.data(), json_str.length());
assert(allPerson2 == allPerson);


// bug: 有重复的记录
iguana::json::from_json(v1, allPerson2.name.data(), allPerson2.name.length());
assert(v == v1);

}

namespace client
{
struct person
{
std::string name;
int64_t age;

    bool operator == (const person& p) const
    {
        return name == p.name && age == p.age;
    }
};

REFLECTION(person, name, age);

}

@asing325 如果用两个独立的iguana::string_stream测试,不用一个ss会不会出现这个问题?

修改了测试代码,增加了注释,提交了请查阅。
vs平台上,pvs-studio静态代码分析工具不错,可以考虑试试看。
另外,很佩服你一个文件搞定json,不过维护起来有点麻烦,要不要考虑用第三方的jsoncpp做解析呢?

问题的原因在这里:
iguana::json::from_json(v1, allPerson2.name.data(), allPerson2.name.length());
iguana现在没有对这个v1做清空处理,内部是直接push_back的,这个v1之前是有3个元素的,导致再push进去了3个元素。你可以用一个新的vector验证。

不过这里iguana内部应该要做一下清空先。
@asing325

已经修复了,更新一下代码再测试一下。
@asing325

我项目中的问题还在,增加了测试用例文件,请查阅 example/test_json_channel.cpp

@asing325
vector里重复记录的问题还在?

之前测试用例,重复数据的问题好了。
我项目中的用法复杂一点,嵌套几层后还原json报错,请查阅新提交的测试文件

error at line :0 col :177 msg:unknown escape char!
error at line :0 col :347 msg:unknown escape char!
error at line :0 col :517 msg:unknown escape char!

请查阅 \example\test_json_channel.cpp
。。。
UserMsg msg;
msg.id = 0;
msg.msg = jsonStr;

auto str = ToJsonString(msg);
UserMsg msg2;
bOK = ToUserData(msg2, str);
// bug: 这里还原不出来了,打印了错误提示
assert(bOK);
assert(msg.id == msg2.id);
assert(msg.msg == msg2.msg);

datas2.clear();
// bug: 这里死循环了
bOK = ToUserData(datas2, msg2.msg);
assert(bOK);
assert(datas2.size() == datas.size());
assert(datas[0].seats.size() == datas2[0].seats.size());

@asing325 先把死循环的问题解决,更新一下代码看看死循环是不是解决了。

死循环解决了,数据不正确

建议你不要把json串多次序列化,目前只支持序列化一次json字符串。
你如果希望支持多层嵌套就用嵌套结构体。
另外,为了效率,from_json会修改原来的json串,所以from_json之后原来的字符串就无效了,不能再用了。

1、“你如果希望支持多层嵌套就用嵌套结构体”,,,好的,可以去掉特殊用法。
2、“为了效率,from_json会修改原来的json串,”,,,可以接受,后面也没有用那个字符串了。

另外一个问题,g_has_error这个全局变量能不能去掉啊,不然转换数据的时候还得全局加锁,不然 from_json 函数的返回值可能不正确,影响代码流程

需要向外面返回解析结果是否正确,不加这个就只能抛异常了,这样感觉也不太好。

你可以把g_has_error改成一个原子变量,这样可以保证这个变量是线程安全的。