0

我希望使用json-c库来转换 .json 文档中包含的所有对象:

{
    "name": "mathieu",
    "password": "def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942",
    "salt": "nXvtCQEqx8l1uNheIJLoO8VI7049vgIS",
    "email": "mathieu@mail.com"
}
{
    "name": "cesar",
    "password": "487b36f3e5a3a74ec3bf2bf48cbc49cde249b08977d22394122c9d512d0e94b4",
    "salt": "Q3QnWFZnLXg8217V1uLaBka6R3CZvCfl",
    "email": "cesar@mail.com"
}

为了转换它们(目前我只想显示),我使用以下代码(我按照这个Youtube 视频中的说明进行操作):

#include <stdio.h>
#include <stdlib.h>
#include <json-c/json.h>

//#include "../../include/personnes.h"

//int parseMyJsonPersonne(){
int main(){
    FILE* fichier = NULL;
    char buffer[1024];

    struct json_object *parsed_json;
    struct json_object *name;
    struct json_object *password;
    struct json_object *salt;
    struct json_object *email;

    fichier = fopen("../../data/Personne.json", "r");
    if (fichier != NULL) {
        fread(buffer, 1024, 1, fichier);
    }
    else {
        printf("Une ERREUR est survenue lors du chargement des différents comptes\n");
        return 1;
    }
    fclose(fichier);

    printf("buffer : %s\n", buffer);

    parsed_json = json_tokener_parse(buffer);

    json_object_object_get_ex(parsed_json, "name", &name);
    json_object_object_get_ex(parsed_json, "password", &password);
    json_object_object_get_ex(parsed_json, "salt", &salt);
    json_object_object_get_ex(parsed_json, "email", &email);

    printf("name : %s\n", json_object_get_string(name));
    printf("password : %s\n", json_object_get_string(password));
    printf("salt : %s\n", json_object_get_string(salt));
    printf("email : %s\n", json_object_get_string(email));

    json_object_object_get_ex(parsed_json, "name", &name);
    printf("name 2 : %s\n", json_object_get_string(name));

    free(name);
    free(password);
    free(salt);
    free(email);

    return 0;
}

这是编译和执行后终端向我显示的内容:

buffer : {
    "name": "mathieu",
    "password": "def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942",
    "salt": "nXvtCQEqx8l1uNheIJLoO8VI7049vgIS",
    "email": "mathieu@mail.com"
}
{
    "name": "cesar",
    "password": "487b36f3e5a3a74ec3bf2bf48cbc49cde249b08977d22394122c9d512d0e94b4",
    "salt": "Q3QnWFZnLXg8217V1uLaBka6R3CZvCfl",
    "email": "cesar@mail.com"
}

name : mathieu
password : def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942
salt : nXvtCQEqx8l1uNheIJLoO8VI7049vgIS
email : mathieu@mail.com
name 2 : mathieu

所以这是我的各种问题

  1. 如何转到下一个对象并知道 .json 中的对象数量?
  2. 我认为如果对象数量太大,将缓冲区初始化为1024会导致问题,那么有没有办法让缓冲区一个一个地获取对象?
  3. 我有一种感觉,内存的释放不对,是我忘记了一些free吗?
4

1 回答 1

0

json_tokener_parse()返回它在提供的缓冲区中找到的第一个 JSON 对象。当你调用它时,你把它放在一个名为parsed_json.

自从你第二次试图得到你一直传递的名字以来parsed_json

json_object_object_get_ex(parsed_json, "name", &name);
printf("name 2 : %s\n", json_object_get_string(name));

检索到相同的名称。


您需要做的是通过调用json_tokener_parse_ex. 根据文档,它的接口是

JSON_EXPORT struct json_object* json_tokener_parse_ex( 
    struct json_tokener *   tok,
    const char *    str,
    int     len 
)

在哪里

参数

tok 一个 json_tokener 先前分配的json_tokener_new()

str 具有任何有效 JSON 表达式或部分的字符串。这不需要以空值终止。

len str 的长度

它基本上会解析输入缓冲区json_tokener_parse(),但在内部使用令牌将能够在需要解析更多内容时提醒您。这是通过返回来完成的json_tokener_continue

请参阅文档以获取更多信息。我只是在这里引用上面提供的文档链接中显示的示例:

json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;

do
{
    mystring = ...  // get JSON string, e.g. read from file, etc...
    stringlen = strlen(mystring);
    jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);

if (jerr != json_tokener_success)
{
    fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));

    // Handle errors, as appropriate for your application.
}

if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
    // Handle extra characters after parsed object as desired.
    // e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.

替代解决方案

至于其他问题,我确认如果 JSON 对象的数量不断增加,首先或稍后您的缓​​冲区会出现问题。处理这个问题会导致另一种解决方案。

当然,您可以一一阅读,但是在从文件中读取时,您必须自己执行一些解析。但是,如果您确定文件结构将始终是您在问题中发布的文件结构,那么您很幸运:您可以做的是

  1. fopen()文件,就像现在一样
  2. fgets()使用而不是逐行读取文件fread()。将数据放入buffer
  3. 检查最后一行是否包含右花括号}。如果是,请继续
  4. 现在buffer只包含一个对象。json_tokener_parse()像以前一样调用,并打印解析的数据json_object_object_get_ex()
  5. 重复点(2)直到到达文件末尾
  6. fclose()文件
于 2020-04-09T10:43:40.860 回答