How to update contents of an array and updating a JSON file?

63 views
Skip to first unread message

Jan Karlo Camero

unread,
Jan 29, 2020, 3:34:24 PM1/29/20
to Jansson users
Hi ,

I have a JSON file called "network_sysconfig.cfg".
My aim is to read the JSON file, then update the "interfaces" array and then eventually update the file.
In my code below, json_dump_file() returns -1.


The JSON file contents look like this:

{
    "hostname": "defaulthostname",
    "gateway": "192.168.1.1",
    "interfaces": [
        {
            "description": "Port 1 network settings",
            "port_number": "1",
            "ip_address": "192.168.3.1/24",
            "mac_addr" : "00:00:00:00:00:00"
        },
        {
            "description": "Port 2 network settings",
            "port_number": "2",
            "ip_address": "192.168.4.1/24",
            "mac_addr" : "00:00:00:00:00:01"
        }
    ],
    "version": "1.00"
}

I wish to update "interfaces" array specifically index 1 so I wrote my code like this (index 1 was hardcoded):


//root is pass by reference

int updatearr( const char * input, json_t **root)

{


     //set array

     json_t *interface_element, *portinfo_obj;

     json_t *arr = json_object_get(*root, "interfaces");

    

    if(json_is_array(arr))

    {


    //index 1 is hardcoded for simplicity

    interface_element = json_array_get(arr, 1);

    if(NULL == interface_element)

    {

      fprintf(stderr, "update_sysconfig_attr: Error updating \"ip_address\" in %s \n", "./network_sysconfig.cfg");


      json_decref(arr);

      return -1;

    }

    else

    {

        //now we are inside interfaces array, we select ip_address key.

        portinfo_obj = json_object_get(interface_element, "ip_address");

     

        if(NULL == portinfo_obj)

        {

            fprintf(stderr, "update_sysconfig_attr: Error updating \"ip_address\" in %s \n",

                 "./network_sysconfig.cfg");


         json_decref(interface_element);

         json_decref(arr);

         return -1;

        }

       else

       {

           // here we set our intended value for ip_address

           if( -1 == json_string_set(portinfo_obj, input) )

           {

                fprintf(stderr, "update_sysconfig_attr: Error updating \"ip_address\" in %s \n",

                 cfg_fortiiot_networkconf);


                 json_decref(portinfo_obj);

                 json_decref(interface_element);

                 json_decref(arr);

                return -1;

          }

       }

     }

   }


   json_decref(portinfo_obj);

   json_decref(interface_element);

   json_decref(arr);


   return 0;

}


int main(int argc, char *argv[])

{


    json_error_t json_error;

    json_t *root = json_load_file("./sysconfig.cfg",0,&json_error);  //load JSON file




   updatearr( newipnum, &root);


   if(0 != json_dump_file(root, "./network_sysconfig.cfg", JSON_INDENT(4)))

   {

      fprintf(stderr, "File Error\n");   //I cant properly write to my file. The resulting file is shown below.

   }


   json_decref(root);

  

   return 1;

}




Resulting file:

The resulting file is broken until interfaces and I get a -1 return value to json_dump_file()


{
    "hostname": "defaulthostname",
    "gateway": "192.168.1.1",
    "interfaces": [




Am I updating my array/file incorrectly?

Is it due to the fact that I called json_decref() to my json objects inside my updatearr() function?

I am assuming this is ok since I passed root as pass by reference?


Thank in advance!


Graeme Smecher

unread,
Jan 29, 2020, 3:48:59 PM1/29/20
to jansso...@googlegroups.com
Hi Jan,


On 2020-01-29 12:34 p.m., Jan Karlo Camero wrote:
> Am I updating my array/file incorrectly?
>
> Is it due to the fact that I called json_decref() to my json objects
> inside my updatearr() function?

Yes. Please take a look at the documentation for json_array_get() and
json_object_get():

https://jansson.readthedocs.io/en/2.8/apiref.html#array
https://jansson.readthedocs.io/en/2.8/apiref.html#object

Both of these calls return a borrowed references, so your json_decref()
calls at the botton of updatearr() are in error. As a result, your JSON
object contains references to free'd pointers and is corrupt when it
arrives at json_dump_file().

As usual, valgrind gives you some useful hints about what the error is,
and where it occurred. I recommend you try it out to gain confidence and
visibility into your reference counts.

> I am assuming this is ok since I passed root as pass by reference?

Jansson's reference-counting mechanism is completely distinct from
pointer management in C. There is no way you can affect Jansson's
reference counts except directly, by using the Jansson API.

best,
Graeme
pEpkey.asc

Jan Karlo Camero

unread,
Jan 29, 2020, 4:08:07 PM1/29/20
to Jansson users
Perfect!

I now understand thank you.
The fix worked and I used valgrind with no resulting errors.

Many thanks!
Reply all
Reply to author
Forward
0 new messages