我有一个名为 name.json 的 Json 文件,可以在下面看到此类 Json 文件的示例
{
"set": 5,
"low": 0,
"draw_set": "0.1 up to 0.3",
"Wupet": "Hold",
"": null
}
Run Code Online (Sandbox Code Playgroud)
但也有可能是另外一次 Json 文件具有另一种结构。
{
"set": 5,
"low": 0,
"draw_set": "0.1 up to 0.3",
"W_set": "Ramp 1.5 ?C/min",
"Wset": 0,
"Wupet": "Hold",
"": null
}
Run Code Online (Sandbox Code Playgroud)
我想将此 Json 文件的输入(每个文件中的属性及其类型可以不同)转换为 C 结构,其中结构自动检测 Json 文件中存在哪些属性(及其类型)。“”中的属性“”:null(可以给定一个随机的属性名)
然后我想自动将Json值的值分配给对象Book1的结构体。
我的代码计划
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Books {
float set[50];
int low[50];
char draw_set[100];
char Wupet[100];
};
int main( ) {
/* Read name.Json file */
struct Books Book1; /* Declare Book1 of type Book */
/* Convert content Json to Struct Book1 with it's actual values*/
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编辑:如果 Json 文件中存在“Wset”和“W_set”键,我不想忽略它们。Json 文件的键正在改变一切(未来可能会出现许多未知的属性)。不能保证密钥的数量。保证“多行拆分”属性?应该给空键名一个随机名称(多个键可以与空键名一起出现)结构的属性类型应该被自动检测和创建。Json 文件包含单个记录(对象)
我想在运行时处理这些结构。
应该自动检测和创建结构的属性类型。
如果没有一些古怪的宏,你就无法做到这一点。C 中结构体的字段在编译时是固定的。
自动填充结构需要能够找出结构的字段和类型:反射。C 没有反射。你可以写一些聪明的宏,但对于这么简单的事情来说可能不值得。
如果没有一些古怪的宏,根据 JSON 自动将字段添加到您的结构中也是不可能的。
相反,我们将把 JSON 解析成一个灵活的数据结构,你可以用它做任何你喜欢的事情。如果要将它们全部放入一个结构中,则该结构必须包含所有可能的字段。有一些技术可以编写扩展结构,因此您可以Book为不同类型的书籍拥有一个基本的和附加的扩展结构。
JSON-Glib两者都提供。它将 JSON 解析为 JsonNodes,它可以是 JsonArrays 或 JsonObjects。然后你可以对他们做任何你想做的事情。
在我们这样做之前,结构体需要做一些工作。
struct Books {
gint64 set;
gint64 low;
const char *draw_set;
const char *wupet;
};
Run Code Online (Sandbox Code Playgroud)
set 不是浮点数,而是整数。
我们使用 GLib 类型来匹配 GLib 库返回的内容并避免大量溢出。
读取输入时应避免使用固定大小的缓冲区,它们很容易溢出。相反,JSON-Glib 可以分配正确的内存量。我们将复制它并存储一个指向它的指针。
这是使用 JSON-Glib 解析 JSON 文件并手动填充结构的示例。
#include <stdlib.h>
#include <stdio.h>
#include <glib-object.h>
#include <json-glib/json-glib.h>
struct Books {
gint64 set;
gint64 low;
char *draw_set;
char *wupet;
};
int main(int argc, char** argv) {
GError *error = NULL;
if (argc < 2) {
printf("Usage: test <filename.json>\n");
return EXIT_FAILURE;
}
// Parse the JSON from the file
JsonParser *parser = json_parser_new();
json_parser_load_from_file(parser, argv[1], &error);
if(error) {
printf("Unable to parse `%s': %s\n", argv[1], error->message);
g_error_free(error);
g_object_unref(parser);
return EXIT_FAILURE;
}
// Get the root
JsonNode *root = json_parser_get_root(parser);
// Turn the root into a JSON object
JsonObject *stuff = json_node_get_object(root);
// Get each object member and assign it to the struct.
struct Books book = {
.set = json_object_get_int_member(stuff, "set"),
.low = json_object_get_int_member(stuff, "low"),
// Duplicate the strings to avoid pointing to memory inside the parser.
.draw_set = g_strdup(json_object_get_string_member(stuff, "draw_set")),
.wupet = g_strdup(json_object_get_string_member(stuff, "Wupet"))
};
printf(
"set = %ld, low = %ld, draw_set = '%s', wupet = '%s'\n",
book.set, book.low, book.draw_set, book.wupet
);
// We're finished working with the parser. Deallocate the
// parser and all the memory it has allocated, including
// the nodes.
g_object_unref(parser);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)