Как преобразовать несколько JSON объектов, используя json - c? - PullRequest
0 голосов
/ 09 апреля 2020

Я буду sh использовать библиотеку 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. Как мне go перейти к следующему объекту и узнать количество объектов в моем. json?
  2. Я думаю, инициализация buffer до 1024 вызовет проблемы, если число объектов слишком велико, поэтому есть ли способ заставить буфер принимать объекты один за другим?
  3. У меня такое ощущение, что освобождение памяти не правильно, я забыл немного бесплатно ?

1 Ответ

0 голосов
/ 09 апреля 2020

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 длина строки

Это в основном будет анализировать входной буфер как 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. Проверьте, содержит ли последняя строка закрывающую фигурную скобку }. Если да, go на
  4. Теперь buffer содержит ровно один объект. Наберите json_tokener_parse(), как вы делали раньше, и напечатайте данные, проанализированные с помощью json_object_object_get_ex()
  5. . Повторите до пункта (2) , пока не будет достигнут конец файла
  6. fclose() файл
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...