【 在 z16166 的大作中提到: 】
: 谢谢
: 看来这个库确实考虑得很全面了
:
https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/: ...................
C++ 反射不完整,所以要么用宏,要么用外部代码生成,这是没办法的
而且其实说实话,用宏的话(比如NLOHMANN_DEFINE_TYPE...),需要 property 一一对应,这种少量还行,类型多了的话,其实是个很累心的活;之后接口改变,修改类型更是容易出错。
写 helloworld 当然无所谓,但是而 json序列化、反序列化 用的最多的是 restful 接口,这个大点的项目随便就几百个接口了,嵌套类型写一写几千个,一一映射太痛苦了。
我写了这么多年 c++ 项目,各种办法都用过,最后用的一劳永逸的方法,其实反而是你之前说的不太方便的那种(在
https://app.quicktype.io/ 上生成)的自动版:
不知道你用没用过 t4 template,也就是 vs 的 tt 模板文件,外部可以调用 TextTransform 来将 tt 文件编译成其他文件。
在 CMakeLists.txt 或者任何 make 文件中增加 PRE_BUILD 脚本,比如
add_custom_command(
TARGET ${PROJECT_NAME} PRE_BUILD
COMMAND "D:/Program files/Microsoft Visual Studio/2022/Community/Common7/IDE/TextTransform.exe"
-out "${CMAKE_CURRENT_SOURCE_DIR}/build/jsonmodel.hpp"
"${CMAKE_CURRENT_SOURCE_DIR}/jsonmodel.tt" )
在 jsonmodel.tt 文件中,遍历某个文件夹中的, *.jsonmode.json 文件,比如 ModelA.jsonmode.json / ModelB.jsonmode.json,然后在 tt 文件中用方便的工具(比如直接用 quicktype 的命令行工具,或者用 c# 的json解析) 生成对应的 NLOHMANN 的 c++ 类型。然后编译的时候,PRE_BUILD 脚本生成 build/jsonmodel.hpp
namespace ModelA{
struct balabala{
}
}
namespace ModelB{
struct balabala{
}
}
然后代码中直接用就行了,之后新加了json类型的话,新建一个 jsonmode.json 文件,把json内容拷进去,编译一下就行了,一劳永逸。
实际应用中, 如果是写客户端代码,你们的 API 按照标准比如 Knife4j / swagger 之类的出了在线文档的话,甚至可以把 Restful API 整个自动化了,在 tt 文件中获取 API 列表,遍历然后生成所有的 API 调用代码和对应的 json 序列化模型。 给你在代码里翻个生成的例子。
#include "WhateverSAApiBase.h"
namespace api_status
{
namespace ns_api_status
{
struct StatusModel {
std::shared_ptr<std::string> status;
std::shared_ptr<int64_t> total;
std::shared_ptr<int64_t> failed;
std::shared_ptr<int64_t> processed;
};
linline void from_json(const json& j, StatusModel& x)
{
auto statusString = get_optional<std::string>(j, "status");
x.status = get_optional<int64_t>(j, "status");
x.total = get_optional<int64_t>(j, "total");
x.failed = get_optional<int64_t>(j, "failed");
x.processed = get_optional<int64_t>(j, "processed");
}
inline void to_json(json& j, const StatusModel& x)
{
j = json::object();
j["status"] = x.status;
j["total"] = x.total;
j["failed"] = x.failed;
j["processed"] = x.processed;
}
} // namespace ns_api_status
class ApiStatus : public WhateverSAApiBase<ns_api_status::StatusModel>
{
private:
QString _id;
public:
ApiStatus(const QString& adaccountId, QString id)
: WhateverSAApiBase<ns_api_status::StatusModel>(QString("whatever/api/v1/%1/editorv1/status").arg(adaccountId)),
_id(id)
{
}
void initialize() override
{
WhateverSAApiBase<ns_api_status::StatusModel>::initialize();
this->add_query_paramters("id", _id);
}
};
} // namespace api_status
真的很方便,服务器新增了接口,修改了接口,本地一键生成一下就行了
※ 修改:·hanjiamajia 于 Aug 4 10:08:02 2023 修改本文·[FROM: 182.150.116.*]
※ 来源:·水木社区
http://www.mysmth.net·[FROM: 182.150.116.*]
修改:hanjiamajia FROM 182.150.116.*
FROM 182.150.116.*