qicosmos / iguana Goto Github PK
View Code? Open in Web Editor NEWuniversal serialization engine
License: Apache License 2.0
universal serialization engine
License: Apache License 2.0
template<typename T>
void check_result(T val, char const *str){
if(val == 0 && strcmp(str,"0") != 0){
g_has_error = true;
}
}
在源代码里面看到有这行代码,序列化std::map<int,自定义结构>时,如果key是0,在某些时候from_json(对象,JSON字符串)会返回false,,但是检查对象时,发现数据都已经反序列化成功。
``struct student
{
int code;
std::string write;
std::string Read;
std::string Descript;
};
REFLECTION(student, code, write, Read, Descript);
struct person
{
std::string name;
int64_t age;
std::list list;
std::list ss;
std::map<std::string, student> dic;
};
REFLECTION(person, name, age, list, ss, dic);
person p;
const char * json = "{ \"name\" : \"tom\", \"age\" : 20,\"list\":[1,2,3],\"ss\":[{\"Code\":1,\"Write\":\"add\",\"Read\":\"cut\",\"Descript\":\"这是描述\"}],\"dic\":{\"a\":{\"Code\":1,\"Write\":\"add\",\"Read\":\"cut\",\"Descript\":\"这是描述\"}}}";
auto r = iguana::json::from_json0(p, json);
以上代码:
1、定义两个结构体--person和student
2、使用iguama把json字符串填充结构体类型的变量
#define DOCTEST_CONFIG_IMPLEMENT
#include "doctest.h"
#include "iguana/json_reader.hpp"
#include "test_headers.h"
#include <iguana/json.hpp>
#include <iguana/json_util.hpp>
#include
TEST_CASE("test parse item num_t") {
{
std::string str{"3e6"};
int p{};
iguana::parse_item(p, str.begin(), str.end());
//throw here because parsed p = 3 and said not correct.
//CHECK(p == 3e6);
}
{
std::string str;
str.append(300, '1');
int p{};
CHECK_THROWS_WITH(iguana::parse_item(p, str.begin(), str.end()),
"Failed to parse number"); // expect to have exception: Number is too long.
}
}
TEST_CASE("test parse item array_t") {
{
std::string str{"[1, -222,"};
std::array<int, 2> test;
///should throw "unexpected end"? but pass..
//CHECK_THROWS_WITH(iguana::parse_item(test, str.begin(), str.end()),
// "Unexpected end");
}
{
std::string str{"[ ] "};
std::array<int, 2> test;
///should throw at this case? but not..
//CHECK_THROWS_WITH(iguana::parse_item(test, str.begin(), str.end()),
// "Unexpected end");
}
{
std::string str{"[ 1.2345] "};
std::array<int, 2> test;
///should throw unexpected end? but throw "expected]"..
//CHECK_THROWS_WITH(iguana::parse_item(test, str.begin(), str.end()),
// "Unexpected end");
}
}
TEST_CASE("test parse item str_t") {
{
// this case throw at json_util@line 132
std::string str{""aaa1""};
std::string test{};
//iguana::parse_item(test, str.begin(), str.end());
//CHECK(test == str);
}
}
// doctest comments
// 'function' : must be 'attribute' - see issue #182
DOCTEST_MSVC_SUPPRESS_WARNING_WITH_PUSH(4007) int main(int argc, char **argv) {
return doctest::Context(argc, argv).run();
}
DOCTEST_MSVC_SUPPRESS_WARNING_POP
struct AAA{
int a;
string b;
int c;
};
struct BBB{
string b;
int c;
int d;
};
AAA a;
BBB b;
a.b="aaa";
a.c=123;
b.b ="bbb";
b.d=754;
func(b, a);
func()执行完后 b.b为"aaa" ,b.c为123 ,b.d不变仍为754
以“六年级-三班-某学生”为例,学生由结构体转换为json字符,作为班级的成员; 班级由结构体转换为json字符,作为年级的成员; 由年级json字符无法解析出classParm成员变量,解析出的结构只有"{"
#include "mainwindow.h"
#include <QApplication>
#include <iostream>
#include "../iguana/iguana/json.hpp"
// 六年级-三班-某学生
struct Person
{
std::string name;
int age;
};
REFLECTION(Person, name, age);
struct Class
{
int classID;
std::string personParm;
};
REFLECTION(Class, classID, personParm)
struct Grade
{
int gradeID;
std::string classParm;
};
REFLECTION(Grade, gradeID, classParm)
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// MainWindow w;
// w.show();
Person p;
p.age = 10;
p.name = "suli";
iguana::string_stream pp;
iguana::json::to_json(pp, p);
std::cout << pp.str() << std::endl;
Person res_p;
iguana::json::from_json(res_p, pp.str().c_str());
Class c;
c.classID = 3;
c.personParm = pp.str();
iguana::string_stream cc;
iguana::json::to_json(cc, c);
std::cout << cc.str() << std::endl;
//const char* dd= "{\"classID\":3,\"personParm\":\"{\\\"name\\\":\\\"suli\\\",\\\"age\\\":10}\"}";
Class res_c;
iguana::json::from_json(res_c, cc.str().c_str());
Grade g;
g.gradeID = 6;
g.classParm = cc.str();
iguana::string_stream gg;
iguana::json::to_json(gg, g);
std::cout << gg.str().c_str() << std::endl;
Grade res_g;
iguana::json::from_json(res_g, gg.str().c_str());
Grade res;
iguana::json::from_json(res, gg.str().c_str());
return a.exec();
}
It's easy to add somelines descripted below.
find_package(Boost)
include_directories(${Boost_INCLUDE_DIRS})
namespace Model {
struct BookData {
std::string name;
std::string pubs;
int pages;
std::string types;
};
REFLECTION(BookData, name, pages, pubs, types);
}
const char * bookJson = "{\"name\":\"my book\",\"types\":\"aaa\",\"pages\":11,\"pubs\":\"bbb\"}";
Model::BookData book;
iguana::json::from_json(book, bookJson);
cout << book.name << endl;//正常输出
cout << book.types << endl;//没有输出
`template<typename T, typename V>
void set_field_value(T& to_obj, std::string_view to_field_name, const V& from_v)
{
using M = decltype(iguana_reflect_members(to_obj));
auto tp = M::apply_impl();
constexpr auto Size = M::value();
auto index = iguana::get_index(to_field_name);
tuple_switch(index, tp, [&](auto& v) {
using type_v = decltype(std::declval().*std::declval<decltype(v)>());
to_obj.*v = (type_v)from_v;
}, std::make_index_sequence{});
}
///////////////////////////////////////////////
struct person
{
std::string name;
int age = 0;
};
REFLECTION(person, age, name);
int main()
{
person p;
iguana::set_field_value(p, "name", "Tom");
iguana::set_field_value(p, "age", 20);
return getchar();
}`
I didn't get the right answer when i take someone test
std::list<char> str;
str.push_back('\"');
str.push_back('a');
str.push_back('\\');
str.push_back('\"');
std::string test{};
iguana::parse_item(test, str.begin(), str.end());
CHECK(test == "a");
the result of test is a\"
, not a
The string to be deserialized has fewer words,maybe lesser than 7, it will crash at json_util@line 132
需求:只需要解析json里的某些字段,不管json怎么变,只要结构体要求的字段在就能解析。
当前:结构体必须要有json的所有字段。
对于自定义的类,序列化代码已经很少了,不错
1)流能支持 std::stringstream吗?
2)类外定义,可以放到类内定义,这样也许可以少些一个类名。
struct one_t
{
int id;
};
REFLECTION(one_t, id);
能不能够改为:
struct one_t
{
int id;
REFLECTIONINNER( id);
};
3)private/protect可以支持吗?
4)编译性能的benchmark。
struct A { int a; std::string b; }; struct B { A a; std::string c; };
REFLECTION(A, a,b);
REFLECTION(B, a,c);
序列化:{"a":{"a":1,"b":"123"},"c":"123"} json没问题。
但是序列化:{"a":{"a":1},"c":"123"} 会陷入死循环
容器为空时,序列化时 未做判断
template<typename InputIt, typename T, typename F>
T join(InputIt first, InputIt last, const T &delim, const F &f) {
if (first == last) return T();
T t = f(*first++);
while (first != last) {
t += delim;
t += f(*first++);
}
return t;
}
template<typename Stream, typename InputIt, typename T, typename F>
void join(Stream& ss, InputIt first, InputIt last, const T &delim, const F &f) {
if (first == last) return;
f(*first++);
while (first != last) {
ss.put(delim);
f(*first++);
}
}
Qt版本5.12.0,定义的结构体,里面使用了QString / qreal / QMap 等Qt自定义的类型。可以使用该库序列化吗
或者,使用自己的json库来做序列化,序列化后存文件要更友好查看一点。
#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);
}
error LNK2005: "void __cdecl iguana::xml::detail::get_value(char const *,unsigned __int64,class std::basic_string<char,struct std::char_traits,class std::allocator > &)" (?get_value@detail@xml@iguana@@YAXPEBD_KAEAV?$basic_string@DU?$char_traits@D@std@@v?$allocator@D@2@@std@@@z) 已经在 xxx.obj中定义
fatal error LNK1169: [找到一个或多个多重定义的符号]
#include <iostream>
#include "iguana/json.hpp"
struct Model {
std::string str;
int num;
};
REFLECTION (Model, str, num);
void parseJson (const char *json)
{
Model model;
model.str = "";
model.num = 0;
iguana::json::from_json (model, json);
std::cout << "str: '" << model.str << "', "
<< "num: " << model.num << std::endl;
}
//$ clang++ json_test.cpp -std=c++14 -o json_test && ./json_test
int main (int argc, char *argv[])
{
parseJson (R"({ "str": "string", "num": 6, "dummy": 0 })"); // str: 'string', num: 6
parseJson (R"({ "str": "string", "num": 6 })"); // str: 'string', num: 6
parseJson (R"({ "str": "string" })"); // str: 'string', num: 0
parseJson (R"({ "dummy": 0 })"); // str: '', num: 0
parseJson (R"({ "dummy": 0, "num": 6 })"); // str: '', num: 0
parseJson (R"({ "dummy": 0, "num": 6, "str": "string" })"); // str: '', num: 0
return 0;
}
json
with some dummy field...json字符串里面属性位置顺序和REFLECTION里面指定的位置对不上时会序列化不成功?
或者json字符串属性少于REFLECTION里面指定的也会序列化不成功?
请问是不是会有这个问题呢?
/root/source/vcpkg/installed/x64-linux/include/iguana/json.hpp:1213:13: error: variable of non-literal type 'iguana::json::reader_t' cannot be
defined in a constexpr function
reader_t rd(buf, len);
hope to be replied.
hi:
In some cases, I want to use char array in struct, not use std::string, I found it deal char array as c_array, is there any suggestion to make it like string
struct string_ref {
char const *str;
size_t len;
int length() const {
auto size = len;
for (size_t i = 0; i < len; ++i) {
if (str[i] == 92 || str[i] == 116 || str[i] == 50) // 92: ‘\’, 116: ‘t’, 50: ‘2’
size -= 1;
}
return static_cast(size);
}
bool operator!=(const char *data) const {
auto const str_length = strlen(data);
if (len != str_length) {
if (length() != str_length)
return true;
}
for (size_t i = 0; i < str_length; ++i) {
if (str[i] != data[i]) {
return true;
}
}
return false;
}
};
}
不知道上面的length() 函数中为何当str[i]=92,116,50的时候size要-1?
我在尝试使用这个库时遇到一些问题,对于json字符串的解析,没有安全检查,比如某个字段类型不正确,不存在,iguana::json::from_json0()会仍然返回true,并且在对象中使用不正确的值.
举个例子:
struct test
{
std::string username;
std::string password;
long long id;
bool error;
};
REFLECTION(test, username, password, id, error);
int main(void)
{
test test1;
std::string str1 = "{"username1":"test","password":"test","id": 10.1, "error": false}";
auto ret = iguana::json::from_json0(test1, str1.c_str(), str1.length());
std::cout << test1.username << std::endl;
std::cout << test1.password << std::endl;
std::cout << test1.id << std::endl;
std::cout << std::boolalpha << test1.error << std::endl;
std::cout << std::boolalpha << ret << std::endl;
return 0;
}
以上代码,json字符串不存在username这个key,并且id的类型也不正确,但是解析仍然返回true. 我认为该库无法用于生产环境,因为解析的正确性不应该由使用库的用户来检查.
/* arg list expand macro, now support 120 args */
#define MAKE_ARG_LIST_1(op, arg, ...) op(arg)
#define MAKE_ARG_LIST_2(op, arg, ...) \
op(arg), MARCO_EXPAND(MAKE_ARG_LIST_1(op, __VA_ARGS__))
#define MAKE_ARG_LIST_3(op, arg, ...) \
op(arg), MARCO_EXPAND(MAKE_ARG_LIST_2(op, __VA_ARGS__))
#define MAKE_ARG_LIST_4(op, arg, ...) \
...
结构体数组怎么支持啊 c类型的 谢谢大佬
看了下只使用了lexical_cast,是否可以考虑将之移除?
enum COLOR {
RED,
GREEN,
BLUE
};
struct S{
int a;
COLOR c;
};
S data;
data.a = 1;
data.c = GREEN;
iguana::json::to_json(ss, data);
cout << ss.str() << endl;
输出{"a":1,"c":2}
期望输出 ("a":1,"c":GREEN)
#include "stdafx.h"
#include "iguana\json.hpp"
#include <iostream>
struct struct_A
{
int aa[2];
};
REFLECTION(struct_A, aa)
int main()
{
struct_A A = { {1,2} };
iguana::string_stream ss;
iguana::json::to_json(ss, A);
auto json_s = ss.str();
std::cout << json_s << std::endl;
struct_A A_;
iguana::json::from_json(A_, json_s.c_str());
return 0;
}
数组在from_json过不去,vector可以
refactor: improve json parsing performance; fix some bugs; use c++20;
I met build error in my env. Do we have tutorial about how to build this project in Linux env?
my gcc version is 5.30
Build log:
[mcong@localhost build]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/local/gcc/libexec/gcc/x86_64-unknown-linux-gnu/5.3.0/lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: ./configure --prefix=/usr/local/gcc --enable-threads=posix --disable-checking --enable-languages=c,c++ --disable-multilib --with-gmp=/usr/local/lib --with-mpfr=/usr/local/lib --with-mpc=/usr/local/lib
Thread model: posix
gcc version 5.3.0 (GCC)
[mcong@localhost build]$ vi /home/mcong/study/github/iguana/reflection.hpp
[mcong@localhost build]$ make
Scanning dependencies of target json_example
[ 33%] Building CXX object CMakeFiles/json_example.dir/example/json_example.cpp.o
In file included from /home/mcong/study/github/iguana/json.hpp:8:0,
from /home/mcong/study/github/example/json_example.cpp:1:
/home/mcong/study/github/iguana/reflection.hpp:326:55: error: global qualification of class name is invalid before ‘{’ token
template<>struct ::iguana_reflect_members<STRUCT_NAME>{
^
/home/mcong/study/github/iguana/reflection.hpp:338:5: note: in expansion of macro ‘MAKE_META_DATA_IMPL’
MAKE_META_DATA_IMPL(STRUCT_NAME, MAKE_ARG_LIST(N, &STRUCT_NAME::OBJECT, VA_ARGS))
^
/home/mcong/study/github/iguana/reflection.hpp:343:1: note: in expansion of macro ‘MAKE_META_DATA’
MAKE_META_DATA(STRUCT_NAME, GET_ARG_COUNT(VA_ARGS), VA_ARGS)
^
/home/mcong/study/github/example/json_example.cpp:11:2: note: in expansion of macro ‘REFLECTION’
REFLECTION(person, name, age);
^
/home/mcong/study/github/example/json_example.cpp: In function ‘int main()’:
/home/mcong/study/github/example/json_example.cpp:19:29: error: no matching function for call to ‘to_json(iguana::string_stream&, client::person&)’
iguana::json::to_json(ss, p);
^
In file included from /home/mcong/study/github/example/json_example.cpp:1:0:
/home/mcong/study/github/iguana/json.hpp:138:7: note: candidate: template<class Stream, class T> std::enable_if_t<iguana::is_reflection::value> iguana::json::to_json(Stream&, T&&)
auto to_json(Stream& s, T &&t) -> std::enable_if_t<is_reflection::value>
^
/home/mcong/study/github/iguana/json.hpp:138:7: note: template argument deduction/substitution failed:
/home/mcong/study/github/iguana/json.hpp:161:7: note: candidate: template<class Stream, class T> void iguana::json::to_json(Stream&, const std::vector&)
void to_json(Stream& s, const std::vector &v) {
^
/home/mcong/study/github/iguana/json.hpp:161:7: note: template argument deduction/substitution failed:
/home/mcong/study/github/example/json_example.cpp:19:29: note: ‘client::person’ is not derived from ‘const std::vector’
iguana::json::to_json(ss, p);
^
In file included from /home/mcong/study/github/example/json_example.cpp:1:0:
/home/mcong/study/github/iguana/json.hpp:166:7: note: candidate: template<class Stream, class ... Args> void iguana::json::to_json(Stream&, std::tuple<_Elements ...>)
void to_json(Stream& s, std::tuple<Args...> tp) {
^
/home/mcong/study/github/iguana/json.hpp:166:7: note: template argument deduction/substitution failed:
/home/mcong/study/github/example/json_example.cpp:19:29: note: ‘client::person’ is not derived from ‘std::tuple<_Elements ...>’
iguana::json::to_json(ss, p);
^
/home/mcong/study/github/example/json_example.cpp:25:64: error: no matching function for call to ‘from_json(client::person&, const char*, std::__cxx11::basic_string::size_type)’
iguana::json::from_json(p2, json_str.data(), json_str.length());
^
In file included from /home/mcong/study/github/example/json_example.cpp:1:0:
/home/mcong/study/github/iguana/json.hpp:1030:7: note: candidate: template<class T, class> void iguana::json::from_json(T&&, const char*, size_t)
void from_json(T &&t, const char *buf, size_t len = -1) {
^
/home/mcong/study/github/iguana/json.hpp:1030:7: note: template argument deduction/substitution failed:
make[2]: *** [CMakeFiles/json_example.dir/example/json_example.cpp.o] Error 1
make[1]: *** [CMakeFiles/json_example.dir/all] Error 2
make: *** [all] Error 2
struct SampleInfo
{
std::string features;
std::string modpath;
int filetype;
std::string ip;
__int64 time;
SampleInfo()
{
filetype = SFT_DLL;
time = 0;
}
}
std::string buf = R"({"status":{"msg":"","code":0},"result":[{"features":"9a/AFjFJnblBG7e6YrLm4R0SCGNZPgZJankK0hA=","modpath":"F:\xxx\榫嶄箣瀵嗕紶瀹屾暣瀹㈡埛12.01\InterceptAttacks.dll","filetype":1,"ip":"","time":1551259301}]})";
在解析上面这个json是会出问题 ,一直分配内存直到分配失败,出问题是乱码那个+路径, 路径是2个斜杠的编辑怎么变成一个了
Hi bro, after reading your project, thank you very much for sharing such good things
I have a question:
Because the project is written in xxx.hpp and c++ template
I want to make package to dll and .h ,but it's too hard.
So I want to ask how to do this
Thanks !
嗨,兄弟,看完你的项目,非常感谢你分享这么好的东西
我有一个问题:
因为项目是用xxx.hpp和c++模板编写的
我想让它封装为dll和。h,但它太难了。
我想问一下如何做到这一点
谢谢!
json.hpp支持char[],但是换成msgpack就编译失败了,
请看看能不能支持一下啊,第三方接口里面有char[],没有办法回避~
#include <iguana/msgpack.hpp>
namespace client
{
struct game
{
char ip[32]; // add for test
std::string name;
double price;
};
REFLECTION(game,ip, name, price);
}
1>------ 已启动生成: 项目: msgpack_example, 配置: Debug Win32 ------
1>msgpack_example.cpp
\iguana\iguana\reflection.hpp(388): error C2672: “std::make_tuple”: 未找到匹配的重载函数
struct TaskQuery_User
{
int id;
string email;
string nickName;
string avatar;
};
REFLECTION(TaskQuery_User, id, email, nickName, avatar);
struct TaskQuery_List
{
TaskQuery_User user;
};
REFLECTION(TaskQuery_List,user);
struct TaskQuery_data
{
vector<TaskQuery_List> list;
};
REFLECTION(TaskQuery_data, list);
struct TaskQuery_Json
{
TaskQuery_data data;
long long timestamp;
};
REFLECTION(TaskQuery_Json, data, timestamp);
int main(void)
{
string strTaskQueryJsonResult = "{"data":{"list":[{"user":null}]},"timestamp":1533134762747}";
TaskQuery_Json taskQueryJson;
iguana::json::from_json(taskQueryJson,strTaskQueryJsonResult.c_str(), strTaskQueryJsonResult.length());
return 0;
}
用这个库来解析和序列化比较好吧?
毕竟这个专精于json,功能更多更强大,支持的功能更多,比起自己来解析应该更稳定一些
https://github.com/nlohmann/json
#include "json.hpp"
#include "reflection.hpp"
struct ita
{
int64_t b;
};
REFLECTION(ita, b)
int main()
{
ita f{1 };
iguana::string_stream ss;
iguana::json::to_json(ss, f);
auto json_str = ss.str();
std::cout << json_str << std::endl;
return 0;
}
编译报错(vs2017)
struct ca{
std::string c_id;
std::string ca_id;
std::string c_name;
float pan; // =0.0;
float tilt;
float zoom;
}
REFLECTION(ca, c_id,ca_id, c_name, pan, tilt , zoom)
执行完上面的定义后,在一个执行函数中定义这个ca类
ca tb_ca;
发现成员变量的值 tb_ca.pan 不为接近于0的一个数,而为一个正的有意义的值。
请问是内存溢出的错误嘛,该如何修改。
#include <iostream>
#include "json.hpp"
#include "xml.hpp"
struct person
{
std::string name;
int age;
};
REFLECTION(person, name, age)
/* REFLECTION(person, name, age)展开后的代码如下
constexpr std::array<const char*, 2> arr_person = { "name" , "age" };
template<>
struct Members<person> {
constexpr decltype(auto) static apply() {
return std::make_tuple(&person::name, &person::age);
}
using type = void;
constexpr static const char *name = "person";
constexpr static const size_t value = 2;
constexpr static const std::array<const char*, value>& arr = arr_person;
};
*/
struct one_t
{
int id;
};
REFLECTION(one_t, id);
struct third_t
{
std::string name;
one_t one;
int age;
};
REFLECTION(third, name, one, age);
struct composit_t
{
int a;
std::vector<std::string> b;
int c;
std::map<int, int> d;
std::unordered_map<int, int> e;
double f;
std::list<one_t> g;
};
REFLECTION(composit_t, a, b, c, d, e, f, g);
void test_json()
{
person p;
const char * json = "{ \"name\" : \"tom\", \"age\" : 28}";
iguana::json::from_json(p, json);
iguana::string_stream ss;
iguana::json::to_json(ss, p);
std::cout << ss.str() << std::endl;
one_t one = { 2 };
composit_t composit = { 1,{ "tom", "jack" }, 3,{ { 2,3 } },{ { 5,6 } }, 5.3,{ one } };
iguana::string_stream sst;
iguana::json::to_json(sst, composit);
std::cout << sst.str() << std::endl;
const char* str_comp = R"({"a":1, "b":["tom", "jack"], "c":3, "d":{"2":3,"5":6},"e":{"3":4},"f":5.3,"g":[{"id":1},{"id":2}])";
composit_t comp;
iguana::json::from_json(comp, str_comp);
}
//void performance()
//{
// person obj;
// char * json = "{ \"Name\" : \"Boo\", \"Age\" : 28}";
// ajson::load_from_buff(obj, json);
//
// const size_t LEN = 1000000;
//
// //反序列化
// std::cout << "ajson deserialize: ";
// boost::timer t;
// for (size_t i = 0; i < LEN; i++)
// {
// ajson::load_from_buff(obj, json);
// }
// std::cout << t.elapsed() << std::endl;
//
// std::cout << "reflib deserialize: ";
// t.restart();
// for (size_t i = 0; i < LEN; i++)
// {
// iguana::json::from_json(obj, json);
// }
// std::cout << t.elapsed() << std::endl;
//
// //序列化
// std::cout << "ajson serialize: ";
// t.restart();
// ajson::string_stream ss1;
//
// for (size_t i = 0; i < LEN; i++)
// {
// ss1.clear();
// ajson::save_to(ss1, obj);
// }
// std::cout << t.elapsed() << std::endl;
//
// std::cout << "reflib serialize: ";
// t.restart();
//
// iguana::json::string_stream ss;
// for (size_t i = 0; i < LEN; i++)
// {
// ss.clear();
// iguana::json::to_json(ss, obj);
// }
// std::cout << t.elapsed() << std::endl;
//}
void test_xml()
{
person p = {"admin", 20};
iguana::string_stream ss;
iguana::xml::to_xml(ss, p);
std::cout << ss.str() << std::endl;
ss.clear();
two t = { "test", {2}, 4 };
iguana::xml::to_xml(ss, t);
auto result = ss.str();
std::cout << result << std::endl;
std::string xml = " <?xml version=\"1.0\" encoding=\"UTF-8\"> <name>buke</name> <one><id>1</id></one> <age>2</age>";
two t1;
iguana::xml::from_xml(t1, xml.data(), xml.length());
}
template<typename T, typename = std::enable_if_t<is_reflection<T>::value>>
void test_nest_read(T &&t, int indent = 0) {
using namespace std;
for_each(std::forward<T>(t), [=](auto &v, size_t I, bool is_last) {
for (size_t i = 0; i < indent; i++) cout << " ";
cout << I << " : " << get_name<T>(I) << " = " << v << endl;
},
[=](auto &o, size_t I, bool is_last) {
for (size_t i = 0; i < indent; i++) cout << " ";
cout << I << " : 下面是嵌入的成员" << typeid(o).name() << endl;
test_nest_read(o, indent + 1);
});
}
void test_reflection()
{
person p = { "admin", 20 };
constexpr auto fieldname = get_name<person, 0>(); //"name", const char* const. get_name直接返回Members<person>::arr[0]
auto val = get<0>(p); //"admin",std::basic_string. person.*(&person::name)
//person只含有非反射类型成员
for_each(p, [](const auto& item, size_t index, bool is_last) {
std::cout << index <<" "<< item << std::endl;
});
std::cout << std::endl;
two_t two = { "test",{ 2 }, 4 };
//two只嵌套了(一层)一个映射类型成员
for_each(two, [](const auto& item, size_t index, bool is_last) { //处理非反射类型成员
std::cout << index << " " << item << std::endl;
}, [](const auto& o, size_t index, bool is_last) { //处理反射类型成员
std::cout << index << " "<<typeid(o).name()<< std::endl;
});
std::cout << std::endl;
//test_nest_read可以处理无限映射类型嵌套,但是不能处理容器如vector、map,详细可以参考test_json()
third_t third = { "test",{ 2 }, 4 };
test_nest_read(third);
}
int main()
{
test_reflection();
// test_json();
// test_xml();
}
这样导致一次调用from_json失败后,其后反序列化为顺序容器时,即使数据正常,from_json也可能失败。
compiling environment:ubuntu16.04,gcc 12.1.0
code is as following:
struct struct_test_t {
int32_t value;
};
REFLECTION(struct_test_t, value);
struct struct_container_t {
std::vector<struct_test_t> values;
};
REFLECTION(struct_container_t, values);
std::string json_str = "123";
struct_container_t struct_container_obj;
iguana::from_json(struct_container_obj, std::begin(json_str), std::end(json_str)); //编译失败
iguana::string_stream ss;
iguana::json::to_json(ss, struct_container_obj); //可以编译通过
build log is:
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:253:15: error: no matching function for call to ‘parse_item(__gnu_cxx::__alloc_traits<std::allocator<struct_test_t>, struct_test_t>::value_type&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&)’
[build] 253 | parse_item(value.emplace_back(), it, end);
[build] | ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:144:20: note: candidate: ‘template<class U, class It, class auto:65> requires num_t void iguana::parse_item(U&, It&&, auto:65&&)’
[build] 144 | IGUANA_INLINE void parse_item(U &value, It &&it, auto &&end) {
[build] | ^~~~~~~~~~
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:144:20: note: template argument deduction/substitution failed:
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:144:20: note: constraints not satisfied
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp: In substitution of ‘template<class U, class It, class auto:65> requires num_t void iguana::parse_item(U&, It&&, auto:65&&) [with U = struct_test_t; It = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&; auto:65 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&]’:
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:253:15: required from ‘void iguana::parse_item(U&, It&&, auto:68&&) [with U = std::vector<struct_test_t>; It = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&; auto:68 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&]’
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:441:27: required from ‘iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)> [with auto:77 = std::vector<struct_test_t> struct_container_t::* const&]’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/type_traits:2565:26: required by substitution of ‘template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>; _Args = {std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::* const&}]’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/type_traits:2576:55: required from ‘struct std::__result_of_impl<false, false, iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>, std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::* const&>’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/type_traits:2581:12: required from ‘struct std::__invoke_result<iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>, std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::* const&>’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/type_traits:3022:12: required from ‘struct std::invoke_result<iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>, std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::* const&>’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/type_traits:3034:11: required by substitution of ‘template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>; _Args = {std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::* const&}]’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/variant:1093:11: required by substitution of ‘template<class _Visitor, class ... _Variants> using __visit_result_t = std::invoke_result_t<_Visitor, std::__detail::__variant::__get_t<0, _Variants, decltype (std::__detail::__variant::__as(declval<_Variants>())), typename std::variant_alternative<0, typename std::remove_reference<decltype (std::__detail::__variant::__as(declval<_Variants>()))>::type>::type>...> [with _Visitor = iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>; _Variants = {const std::variant<std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::>&}]’
[build] /usr/local/gcc-12.1/include/c++/12.1.0/variant:1819:5: required by substitution of ‘template<class _Visitor, class ... _Variants> constexpr std::__detail::__variant::__visit_result_t<_Visitor, _Variants ...> std::visit(_Visitor&&, _Variants&& ...) [with _Visitor = iguana::from_json<struct_container_t, __gnu_cxx::__normal_iterator<char, std::__cxx11::basic_string > >(struct_container_t&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string >&&)::<lambda(auto:77&&)>; _Variants = {const std::variant<std::vector<struct_test_t, std::allocator<struct_test_t> > struct_container_t::>&}]’
[build] /home/zeeuser/workspace/project/github/iguana/iguana/json_reader.hpp:437:19: required from ‘void iguana::from_json(T&, It&&, It&&) [with T = struct_container_t; It = __gnu_cxx::__normal_iterator<char, std::__cxx11::basic_string >]’
[build] /home/zeeuser/workspace/project/github/iguana/test/json_file_test.cpp:32:20: required from here
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.