c - 将此 Json 文件的输入转换为 C 结构
问题描述
我有一个名为 name.json 的 Json 文件,下面可以看到这样一个 Json 文件的示例
{
"set": 5,
"low": 0,
"draw_set": "0.1 up to 0.3",
"Wupet": "Hold",
"": null
}
但也有可能是 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
}
我想将此 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;
}
编辑:如果 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;
};
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;
}
推荐阅读
- swift - RealityKit – 循环动画变换
- nuxt.js - IntelliJ IDEA 中 tailwindcss 的有问题的代码完成
- mule - 带有地图的过滤器和范围不起作用
- gradle - Gradle 依赖管理:如果 jar 未解析,则使用“子项目”
- active-directory - Salesforce SSO 使用 ADFS 为 AD 中的特定用户组设置
- c - C函数自动连接char数组参数
- php - 我如何在这里成功使用函数 array_intersect() ?
- javascript - 如何遍历数据库中的字段并找到空字段
- python - 禁止(CSRF 令牌丢失或不正确。):Django 表单
- java - 在两个列表中查找所有常见元素