I wish to use the json-c library to transform all my objects contained in my .json document:
{
"name": "mathieu",
"password": "def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942",
"salt": "nXvtCQEqx8l1uNheIJLoO8VI7049vgIS",
"email": "[email protected]"
}
{
"name": "cesar",
"password": "487b36f3e5a3a74ec3bf2bf48cbc49cde249b08977d22394122c9d512d0e94b4",
"salt": "Q3QnWFZnLXg8217V1uLaBka6R3CZvCfl",
"email": "[email protected]"
}
In order to transform them (for the moment I just want to display) I use the following code (I followed the instructions from this Youtube video ) :
#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;
}
And this is what the terminal shows me after compilation and execution :
buffer : {
"name": "mathieu",
"password": "def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942",
"salt": "nXvtCQEqx8l1uNheIJLoO8VI7049vgIS",
"email": "[email protected]"
}
{
"name": "cesar",
"password": "487b36f3e5a3a74ec3bf2bf48cbc49cde249b08977d22394122c9d512d0e94b4",
"salt": "Q3QnWFZnLXg8217V1uLaBka6R3CZvCfl",
"email": "[email protected]"
}
name : mathieu
password : def118e47a2f36b73805b01a5fa3f73b506b98166a929802338db6868e28d942
salt : nXvtCQEqx8l1uNheIJLoO8VI7049vgIS
email : [email protected]
name 2 : mathieu
So here are my various problems :
json_tokener_parse()
returns the first JSON object it finds in the provided buffer. When you call it you place it in a variable called parsed_json
.
Since the second time you try to get the name you keep passing parsed_json
,
json_object_object_get_ex(parsed_json, "name", &name);
printf("name 2 : %s\n", json_object_get_string(name));
the same name is retrieved.
What you need to do is continue parsing by calling json_tokener_parse_ex
. According to documentation, its interface is
JSON_EXPORT struct json_object* json_tokener_parse_ex(
struct json_tokener * tok,
const char * str,
int len
)
where
Parameters
tok a json_tokener previously allocated with
json_tokener_new()
str a string with any valid JSON expression, or portion of. This does not need to be null terminated.
len the length of str
It basically will parse the input buffer like json_tokener_parse()
, but using internally the token will be able to alert you when something more has to be parsered. This is done by returning json_tokener_continue
.
Please refer to documentation in order to get more info. I just quote here the example shown at the documentation link provided above:
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.
As for the other questions, I confirm that first or later you will have problems with your buffer if the number of JSON objects keeps increasing. Dealing with this issue leads to an alternative solution.
Of course you can read them one by one, but you will have to perform some parsering yourself while reading from file. But if you are sure that the file structure will always be the one you posted in your question you are lucky: what you can do is
fopen()
the file, like nowfgets()
instead of fread()
. Put data in buffer
}
. If yes, go onbuffer
contains exactly one object. Call json_tokener_parse()
like you did before, and print the data parsered with json_object_object_get_ex()
fclose()
the file