- 主题:这个json序列化、反序列化的库看着还可以
https://github.com/jake-stewart/cpp-json/blob/main/json.hpp总的框架看着可以。少数代码有可以完善的地方。
缺少对std::wstring的处理,需要自己加上。
因为把一个json串反序列化为struct后,如果要直接用这个struct成员中的字符串来进行大小写无关的处理的话,struct的成员用utf8的std::string不合适,得用std::wstring。
还有个问题是能否增加字段,比如第一版的某个struct有3个字段,第二版在后面加一个字段,变成4个字段。
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*
哪N个?
这个也得自己搞std::wstring,而且每个struct要提供to_json()/from_json(),也比较啰嗦。
倒是也搞了类似的宏NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE/NLOHMANN_DEFINE_TYPE_INTRUSIVE
https://github.com/nlohmann/json#serialization--deserialization
c++不支持反射,这个决定了目前的实现都不怎么爽,基本都是宏和模板结合搞。
用宏的,要在宏里面把struct的每个成员再列一遍,繁琐。。。
这有个用预处理方式搞的
https://github.com/chocolacula/easy_reflection_cpp
需要一个只处理序列化/反序列化的小库
【 在 allegro 的大作中提到: 】
: json序列化/反序列化有N个高star的实现。
: 为什么要花时间研究一个名不见经传的小repo?
:
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*
这个强调性能,貌似不能反序列化到struct
【 在 stub 的大作中提到: 】
: simdjson
--
FROM 123.118.191.*
目前看起来,没有库直接支持std::wstring的序列化反序列化(序列化时自动转为utf8,反序列化时从utf8自动转到std::wstring)。
https://json.nlohmann.me/home/faq/#parse-errors-reading-non-ascii-characters
所以,这个得自己实现。
--
FROM 123.118.191.*
rapidjson以(单线程)速度、小巧见长。好多年前在某个team呆时,那个team选型用过,当时说是有不少要改的问题,现在估计应该好很多了
它应该没有反序列化到struct的功能,这个是它的序列化的例子:
https://github.com/Tencent/rapidjson/blob/master/example/serialize/serialize.cpp
顶楼那个cpp-json倒是focus在序列化、反序列化上,用了个关于宏的奇技淫巧,__VA_OPT__这个c++20才有的宏。
https://www.scs.stanford.edu/~dm/blog/va-opt.html
用llvm的libtooling搞预处理的那个easy_reflection,等于是帮编译器实现反射,也是正途,
不过依赖于compile_commands.json。cmake工程输出这个容易,visual studio的sln工程要输出compile_commands.json,还得装插件,CI服务器麻烦,但可以弄个写死的compile_commands.json,需要预处理的.cpp、.h都写死进去。
【 在 allegro 的大作中提到: 】
: rapidjson可以吗?
: 我用cereal的json接口,内部好像是rapidjson
:
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*
厉害
是在编译时依赖调试信息,还是运行时依赖?
发布出去的elf一般会strip掉调试信息,一是为了尺寸,顺带增大一点别人逆向的难度。
【 在 pfan117 的大作中提到: 】
: 我上班的时候做过C语言结构体序列化,反序列化,依赖dwarf信息。支持结构体嵌套,多维数组,位域。
--
FROM 123.118.191.*
整个就1200行代码,复杂的struct能嵌套(内层的struct需要提供serialize实现,因为宏里的成员列表是没法跨越父struct和子struct的),然后加std::wstring的也好加。
虽然需要c++20编译器,我这边的倒是都能用支持c++20的编译器,应该不是问题。
有点小瑕疵的代码clean一下应该就行了,剩下的就是使用中fix bug完善。里面那两个大的if/else感觉也可以改成用模板偏特化来实现。
小而美的感觉,不过要实际用一下
nlohmann json如果增加std::wstring成员方便的话,也是可以考虑的。
它搞的宏NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE提供了from_json/to_json的默认实现。
【 在 allegro 的大作中提到: 】
: json序列化/反序列化有N个高star的实现。
: 为什么要花时间研究一个名不见经传的小repo?
:
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*
需要动态创建的class才保存用于反射的meta信息就行了
C++的反射标准,还早着呢,最早都得C++26了
【 在 hgoldfish 的大作中提到: 】
: 静态反射也需要额外存储类型信息的吧。
: C++ 现在已经有 typeid() 了。为了实现楼主说的 JSON 序列化与反序列化就必须细化到函数和属性级。那存储的类型信息就太多了。
: 如果 C++ 和 Java 越来越像,我们还不如直接用 Java 算了。
: ...................
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*
to_json()/from_json()比jsoncpp那种手写大量代码从Json::Value里摘出来每个字段,要优雅一些,但每个struct要写这个还是有点啰嗦的
它定义的宏提供了to_json()/from_json()的默认实现,如果字段都是内置支持的类型的话,用这两个宏就够了:
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE、NLOHMANN_DEFINE_TYPE_INTRUSIVE
正在看这个nlohmann json怎么支持std::wstring,如果每个std::wstring类型的字段都要手动加一句转换utf8的代码,那也比较啰嗦。
这个网址可以生成std::wstring的代码,但这个正好是不怎么方便的那种:
https://app.quicktype.io/
cpp-json那个小库只要给std::wstring类型加个偏特化转成uft8,就可以支持,不用每个字段都加个转换utf8的语句。
【 在 CRonaldo31 的大作中提到: 】
: 用过你写的第一个,自己写to_json()/from_json()
--
FROM 123.118.191.*
wstring在windows上就是utf16,在linux上是utf32(或者说在win上适合存放utf16字符,在linux上适合存放utf32字符)
如果在linux上用utf16,需要自己处理utf16的surrogate pair吧,那其实比较麻烦,每个字符不等长。
windows上的api应该是可以直接处理utf16的surrogate pair。
当然,如果只是那26个英文字母的大小写,就不涉及到surrogate pair,把每个surrogate pair当作两个独立的utf16字符处理也能接受。
对utf16字符串,下面这种转换是buggy的实现:
std::wstring data = L"Abc";
std::transform(data.begin(), data.end(), data.begin(), [](wchar_t c){ return std::towlower(c); });
一是处理不了surrogate pair;二是某些语言的字符有问题,例子可以参考下面的:
https://en.cppreference.com/w/cpp/string/wide/towupper
https://en.cppreference.com/w/cpp/string/wide/towlower
我这边大部分字符串是用完就释放了,内存占用不是问题,需要转换大小写再匹配的场合,等长字符串处理方便,而且统一用std::wstring方便源代码跨平台(差异的部分用宏控制)
【 在 kirbyzhou 的大作中提到: 】
: 话说你们用wstring不嫌内存占用太大么?
: 而且wchar_t有16bit和32bit两种实现。
: 我一般都用u16string,偶尔用u32string
: ...................
--
修改:z16166 FROM 123.118.191.*
FROM 123.118.191.*