0

This code aim to extract data from a JSON file:

[{  "name": "alice", "age": 30, "friends" : ["marc","max" ,"alice"] },
{"name": "john", "age": 25,"friends" : ["fr","mario" ,"Jim"]}]

and store the data into a structure so this is the code:

static int c ;
typedef struct {
    char  name[25] ;
    int age ;
    char  *amis ;
} personne ;

static personne * PerArray;
static size_t n_objects;

static int n_friends ;
void ShowInfo ( int n_friends);
    
int main(int argc, char **argv) {
    FILE *fp;
    char buffer[1024];
    struct json_object *parsed_json;
    struct json_object *name;
    struct json_object *age;
    struct json_object *friends;
    struct json_object *friend;
    size_t n_friends;
    struct json_object *parsed_json_1;
    static size_t n_objects;

    size_t j;
    size_t i;

        fp = fp = fopen("file.json","r");
        if ( fp == NULL)
        {
            printf("UNable to open file\n");
            exit(EXIT_FAILURE);
        }

    fread(buffer, 1024, 1, fp);
    fclose(fp);    

    parsed_json = json_tokener_parse(buffer);
    n_objects = json_object_array_length(parsed_json);

    PerArray = (personne *) malloc (n_objects* sizeof(personne)) ;

    for(i=0;i<2;i++)
    {  
        parsed_json_1 = json_object_array_get_idx(parsed_json,i);

        json_object_object_get_ex(parsed_json_1, "name", &name);
        json_object_object_get_ex(parsed_json_1, "age", &age);
        json_object_object_get_ex(parsed_json_1, "friends", &friends);
        strcpy(PerArray[i].name ,json_object_get_string(name));
        printf("Name: %s\n", PerArray[i].name);
        PerArray[i].age = json_object_get_int(age) ;
        printf("Age: %d\n", PerArray[i].age);
        n_friends = json_object_array_length(friends);
        printf("Found %lu friends\n",n_friends);

        PerArray[i].amis = malloc(sizeof(char) * n_friends);    

        for(j=0 ; j< n_friends ; j++)
        {
            friend = json_object_array_get_idx(friends, j);
            printf("%zu. %s\n",j+1,json_object_get_string(friend));
            strcpy(PerArray[i].amis[j] ,json_object_get_string(friend));
            printf("%zu. %s\n",j+1,PerArray[i].amis[j]);
        }
    }
}

I have error of segmentation fault and normally the fault is in this line:

strcpy(PerArray[i].amis[j] ,json_object_get_string(friend));

I'm just putting the string friend in the structure by using strcpy.

Can anyone help?

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
ing23
  • 69
  • 1
  • 1
  • 7
  • `strcpy(PerArray[i].amis[j] ,json_object_get_string(friend))` looks wrong, `PerArray[i].amis[j]` points nowhere. – Jabberwocky Jun 24 '21 at 13:13
  • thanks for your response . yeah i think the error is there anis[j] is a table of char so imust uses strcpy to store the value . – ing23 Jun 24 '21 at 13:17
  • Side note: consistency is important in programming in general. You sometimes have spaces before semicolons and sometimes you don't. Choose one style. Either put spaces before all semicolons (ick) or don't put any spaces before semicolons (preferable), but don't mix the two styles. – Jonathan Leffler Jun 24 '21 at 14:03
  • Side note: Instead of re-inventing the wheel, you may wish to use a lightweight C/C++ JSON parser such as [Frozen](https://github.com/cesanta/frozen). – Andy J Jun 25 '21 at 02:00

1 Answers1

0

This is wrong, PerArray[i].amis[j] points nowhere.

strcpy(PerArray[i].amis[j], json_object_get_string(friend));

You probably want this:

typedef struct {
    char  name[25] ;
    int age ;
    char **amis ;   // two stars here, you need a pointer to a pointer to char
} personne ;
...

PerArray[i].amis = malloc(sizeof(char**) * n_friends); 
// now PerArray[i].amis points to an array of n_friends pointers to char*
...

    const char *pfriend = json_object_get_string(friend);
    PerArray[i].amis[j] = malloc(strlen(pfriend) + 1);
    strcpy(PerArray[i].amis[j], pfriend);

There may be other problems though.

Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • thank you so much it works but i wanna ask you if u don't mind what it does not work with char *amis why we should use double pointer – ing23 Jun 24 '21 at 13:28
  • @ingab because you have more than one friend. A friend is represented by a `const char*`. N friends are N `const char*` therefore you need an array of pointers to `const char *`. Draw it on a piece of paper. – Jabberwocky Jun 24 '21 at 13:30
  • How do you know how many friends a person has? A `NULL` terminated array of pointers to "friend" would serve well here. Personally I would also have all may friends in the `PerArray`, so I would declare `personne **amis;`. But I am not OP, and don't know what his needs are. – HAL9000 Jun 24 '21 at 21:11
  • @HAL9000 I suppose it depends of the JSON file content: `n_objects = json_object_array_length(parsed_json);` – Jabberwocky Jun 24 '21 at 23:06
  • 1
    My issue was not so much knowing how many elements there is in the JSON structure, but knowing how many names `amis` is pointing at. The purpose of a struct like `personne` is to forget about everything JSON related after parsing. When looking at a `personne`, you have no access to the relevant JSON node and cannot rely on `json_object_array_length` any more. The example had 3 friends for both persons, but can you rely on every person having exactly 3 friends? And if you do, you should treat `n_objects != 3` as error. – HAL9000 Jun 24 '21 at 23:35