最近用 C 语言处理 JSON ,感觉很麻烦,就写了这个可以生成 JSON 处理代码的程序。
https://github.com/zltl/json-gen-c
json-gen-c
通过读取结构体 (struct
) 定义文件,生成对应的 JSON 处理代码。这些代码包括 struct
结构体定义,结构体初始化和清理函数,结构体 JSON 编码和解码函数。
使用下列命令构建并安装:
make sudo make install
struct.json-gen-c
文件,内容如下// 结构体定义文件 // 定义结构体 A struct A { // 定义成员变量 int int_val1; int int_val2; long long_val; double double_val; float float_val; sstr_t sstr_val; // 还可以定义数组 int int_val_array[]; // 定义别的结构体类型的变量 B b_val; }; // 定义结构体 B struct B { int id; };
json.gen.c
和 json.gen.h
使用下列命令创建 json
处理代码:
json-gen-c -in struct.json-gen-c -out .
命令创建了 json.gen.c
和 json.gen.h
文件,其中包含了 json
处理代码。同时创建了他们依赖的 sstr.h
和 sstr.c
,这是用于字符串处理的代码,程序中大量地方使用了他们。
json
处理代码 例如要解析 JSON 字符串到结构体 A
:// const char *p_str = "{this is a json string}"; // sstr_t json_str = sstr(pstr); struct A a; A_init(&a); json_unmarshal_A(json_str, &a); // 注意 json_str 是 sstr_t 类型的 // ... A_clear(&a);
要解析 JSON 字符串到结构体 A
的数组 A a[]
:
// const char *p_str = "this is a json string"; // sstr_t json_str = sstr(pstr); struct A *a = NULL; int len = 0; json_unmarshal_array_A(&a, &len, json_str); // 注意 json_str 是 sstr_t 类型的 // ... int i; for (i = 0; i < len; ++i) { A_clear(&a[i]); } free(a);
要将结构体 A
序列化成 JSON 字符串:
struct A a; A_init(&a); // set values to a ... // ... sstr_t json_str = sstr_new(); json_marshal_A(&a, json_str); printf("marshal a to json> %s\n", sstr_cstr(json_str)); sstr_free(json_str); A_clear(&a);
要将结构体数组 A a[]
序列化成 JSON 字符串:
struct A a[3]; for (i = 0; i < 3; ++i) { A_init(&a[i]); // set values to a[i] ... } sstr_t json_str = sstr_new(); json_marshal_array_A(a, 3, json_str); printf("marshal a[] to json> %s\n", sstr_cstr(json_str)); for (i = 0; i < 3; ++i) { A_clear(&a[i]); }
结构定义格式如下:
struct <struct_name> { <field_type> <field_name> []?; <field_type> <field_name> []?; ... };
<field_type>
可以是下列内容之一:
int
long
float
double
sstr_t
如果是成员变量是一个数组,就在变量名后面加 []
。name.
// initialize a struct // always return 0 int <struct_name>_init(struct <struct_name> *obj); // uninitialize a struct // always return 0 int <struct_name>_clear(struct <struct_name> *obj); // marshal a struct to json string. // return 0 if success. int json_marshal_<struct_name>(struct <struct_name>*obj, sstr_t out); // marshal an array of struct to json string. // return 0 if success. int json_marshal_array<struct_name>(struct <struct_name>*obj, int len, sstr_t out); // unmarshal a json string to a struct. // return 0 if success. int json_unmarshal_<struct_name>(sstr_t in, struct <struct_name>*obj); // unmarshal a json string to array of struct // return 0 if success. int json_unmarshal_<struct_name>(sstr_t in, struct <struct_name>**obj, int *len);
1 0o0O0o0O0o 2022-03-24 17:01:25 +08:00 via iPhone |
2 darkbfly666 2022-03-24 17:10:48 +08:00 |
3 darkbfly666 2022-03-24 17:11:27 +08:00 我也再这里推荐一下 这个库 挺好用的 |
![]() | 4 3dwelcome 2022-03-24 17:13:22 +08:00 json 是可变类型,怎么能把结构写死呢。 正常都是把 json 转换成一些可变对象,比如 C++里面的 VARTYPE 对象,一个类型包含了 20 个子类型。 然后根据 json key 再解析具体数据,结构写死一点容错性都没有了。json 毕竟不是 proto ,不可能保证 100%结构正确的。 |
![]() | 5 liaotonglang OP @0o0O0o0O0o quicktype 确实方便啊,要是他有纯 C 的版本,我也不至于那么累。有空的话我给他加一个纯 C 语言依赖 cJSON 的选项。 |
![]() | 6 3dwelcome 2022-03-24 17:17:06 +08:00 举个例子,json 节点下有一堆 array ,有时候为空,有时候为 A 结构,有时候为 B 结构。 具体类型最终是服务器来确定,你这样变成了客户端来确定结构了。 |
![]() | 7 liaotonglang OP @3dwelcome 只是提供一个选项,强类型的 json 处理也有一定的使用场景。比如 golang 的 encoding/json 包,或者 rust 的 serde_json ,他们都提供了强类型的选项,同时支持将 json 解码为无类型结构。 |
![]() | 8 liaotonglang OP @3dwelcome 可惜在 C 语言里,我没找到与他们相对应的方便的语法,就只有强类型结构了 |
![]() | 9 liaotonglang OP @darkbfly666 xpack 看起来很方便,但语法看起来挺奇怪的,我怕会引起同事们反复的提问。如果做 C++的项目我还是会用 nlohmann::json 或者直接用 @0o0O0o0O0o 提到的 quicktype 。 |
![]() | 10 gyf304 2022-03-24 22:10:31 +08:00 via iPhone 写过个类似的 https://v2ex.com/t/753390 |