Search code examples
cjsonjson-c

Parse json file using json-c


I am using the json-c library. I am encountering two issues when trying to parse a json file in C.

If I try and parse the file as it is I get a segmentation fault at json_object_object_foreach().

But if I remove the square bracket at the beginning and end of the json file it works but only parses the first object. I want to parse the whole json file.

Here is my code:

int ParseJson(const char *file)                                                                                                                                                             
{                                                                               
            char *json;                                                                 
            int fd;                                                                     
            struct json_object *obj;                                                    
            struct stat st;                                                             

            fd = open(file, O_RDONLY);                                                  
            json = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);               
            close(fd);                                                                  

            obj = json_tokener_parse(json);                                             

            json_object_object_foreach(obj, key, val) {                                 
                printf("key = %s value = %s\n",key, json_object_get_string(val));       
            }                                                                           

            return 0;                                                                       
}

And here is my json file:

[{
        "test_1": "min",
        "test_2": "max",
        "test_3": "val",
        "test_4": "res",
        "test_5": "var",
        "test_6": "hal"
    }, {
        "fetch_1": 300.00,
        "fetch_2": 100.000,
        "fetch_3": 0.000000,
        "fetch_4": 0.000000,
        "fetch_5": 20.00
    }, {
        "fetch_1": 250.00,
        "fetch_2": 310.000,
        "fetch_3": 3.000000,
        "fetch_4": 7.000000,
        "fetch_5": 18.00
    }, {
        "fetch_1": 450.00,
        "fetch_2": 678.000,
        "fetch_3": 3.000000,
        "fetch_4": 3.000000,
        "fetch_5": 89.00
    }, {
        "fetch_1": 300.00,
        "fetch_2": 100.000,
        "fetch_3": 7.000000,
        "fetch_4": 67.000000,
        "fetch_5": 50.00
    }, {
        "fetch_1": 900.00,
        "fetch_2": 800.000,
        "fetch_3": 6.000000,
        "fetch_4": 5.000000,
        "fetch_5": 30.00
}]

Solution

  • It's a bit funny that you ask about json-c, which I just picked up for my own purposes a short time ago. Anyway, the problem is certainly what @Myst described in comments.

    I was able to duplicate the problem you describe, and running the program under a debugger immediately showed that the segfault occurs during the iteration, not the parse.

    Looking a bit more closely at the code, then, in light of the package's naming conventions, the function (macro, actually) json_object_object_foreach() is designated for use with objects representing JSON objects, not JSON arrays. That's the significance of the second "object" in the name. You must not apply that macros to an object representing a JSON array, as you try to do when the top-level JSON structure in your input is an array. It follows that you must test what type of object you have before determining how to examine it.

    You can determine the type of object you have via json_object_get_type() or json_object_is_type(). For a top-level array, you can get the array length via json_object_array_length(), and use an ordinary for loop to iterate over the index range, retrieving elements via json_object_array_get_idx(). I don't presently see any better alternative, but perhaps someone more experienced with the library will have one to offer.