用C读取json文件

a

复制代码
jconf_t *
read_jconf(const char *file)
{
    static jconf_t conf;
    // 清空数据
    memset(&conf, 0, sizeof(jconf_t));
    // 用于存储文件内容的字符串指针
    char *buf;
    // 解析文件内容后的json结构化数据
    json_value *obj;
    // 打开文件
    FILE *f = fopen(file, "rb");
    if (f == NULL) {
        FATAL("Invalid config path.");
    }
    // 确定文件大小, 并将读取指针移回文件开始
    fseek(f, 0, SEEK_END);
    long pos = ftell(f);
    fseek(f, 0, SEEK_SET);
    if (pos < 0) {
        FATAL("Invalid config path.");
    }
    if (pos >= MAX_CONF_SIZE) {
        FATAL("Too large config file.");
    }
    // 根据文件大小申请内存空间, 注意这边要多申请1个字节用于存放'\0'
    buf = ss_malloc(pos + 1);
    if (buf == NULL) {
        FATAL("No enough memory.");
    }
    // 读取文件内容至buff
    int nread = fread(buf, pos, 1, f);
    if (!nread) {
        FATAL("Failed to read the config file.");
    }
    // 关闭文件
    fclose(f);
    // 关闭字符串结尾
    buf[pos] = '\0'; // end of string

    json_settings settings = { 0UL, 0, NULL, NULL, NULL };
    char error_buf[512];
    // 解析内容至结构化json数据
    obj = json_parse_ex(&settings, buf, pos, error_buf);
    if (obj == NULL) {
        FATAL(error_buf);
    }
    if (obj->type == json_object) {
        unsigned int i, j;
        // 遍历json数据
        for (i = 0; i < obj->u.object.length; i++) {
            // 每一步, 都先读取键名, 然后根据value类型, 读取value内容
            char *name        = obj->u.object.values[i].name;
            json_value *value = obj->u.object.values[i].value;
            if (strcmp(name, "server") == 0) {
                if (value->type == json_array) {
                    for (j = 0; j < value->u.array.length; j++) {
                        if (j >= MAX_REMOTE_NUM) {
                            break;
                        }
                        json_value *v = value->u.array.values[j];
                        char *addr_str = to_string(v);
                        parse_addr(addr_str, conf.remote_addr + j);
                        ss_free(addr_str);
                        conf.remote_num = j + 1;
                    }
                } else if (value->type == json_string) {
                    conf.remote_addr[0].host = to_string(value);
                    conf.remote_addr[0].port = NULL;
                    conf.remote_num          = 1;
                }
            } else if (strcmp(name, "port_password") == 0) {
                if (value->type == json_object) {
                    for (j = 0; j < value->u.object.length; j++) {
                        if (j >= MAX_PORT_NUM) {
                            break;
                        }
                        json_value *v = value->u.object.values[j].value;
                        if (v->type == json_string) {
                            conf.port_password[j].port = ss_strndup(value->u.object.values[j].name,
                                                                    value->u.object.values[j].name_length);
                            conf.port_password[j].password = to_string(v);
                            conf.port_password_num         = j + 1;
                        }
                    }
                }
            } else if (strcmp(name, "server_port") == 0) {
                conf.remote_port = to_string(value);
            }
            // ...
        }
    } else {
        FATAL("Invalid config file");
    }
    // 释放文件内容内存空间
    do {
        free(buf);
        buf = NULL;
    } while (0);
    // 释放结构化json数据空间
    json_value_free(obj);
    return &conf;
}

void *
ss_malloc(size_t size) {
    void *tmp = malloc(size);
    if (tmp == NULL)
        exit(EXIT_FAILURE);
    return tmp;
}
复制代码

.

posted on   Milton  阅读(6619)  评论(2编辑  收藏  举报

编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示