Using JSON with nRF5340 and nRF Connect

Hi

Are there any examples of how to use JSON with nRF5340 DK (or similar) and nRF Connect?

I am using SDK v2.4.1.

I found these files:

c:\ncs\v2.4.1\nrf\ext\iperf3\cjson.c and cjson.h

I wasn't able to include them, so I just copied them to my project folder.\I had to comment out the " iperf_config.h" include in  cjson.h.

I was able to write some basic code:

	cJSON *json_obj;
	cJSON *json_item;
	bool b_result;
	const char *key_str = "key_1";
	char *val_str = "value_1";
	char *json_str = NULL;


	// Create empty JSON object
	json_obj = cJSON_CreateObject();
	// Create a JSON item
	json_item = cJSON_CreateString(val_str);
	// Add an item to this object
	b_result = cJSON_AddItemToObject(json_obj, key_str, json_item);
	// Print the full string
	json_str = cJSON_Print(json_obj);
	// Finished with object, so delete it!
	cJSON_Delete(json_obj);

Initially I got some error about CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE being 0, so in the prj.conf file I set:

CONFIG_MINIMAL_LIBC_MALLOC=y
CONFIG_MINIMAL_LIBC_MALLOC_ARENA_SIZE=1000

This builds if I comment out the call to cJSON_Print().

I can continue to work with this - although I don't understand how I would eventually "release" the json_str created by cJSON_Print() etc.

So I was hoping there was sample code out there, with the correct includes etc.

  • Hey Garrett,

    I was gong to post this Friday, but I wasn't able to log in to DevZone. Regardless, hopefully this helps.

    You need to make sure to set the following config set, which pulls in the cJSON module from <SDK Install Base Path>\v2.5.1\modules\lib\cjson

    CONFIG_CJSON_LIB=y

    Also, note that the library requires that you use another C library other than the minimal lib. Here is the note about that from the config:

    config CJSON_LIB
    	bool "cJSON library"
    	# Since minimal libc lacks sscanf and strtod we need to use newlibc
    	# Allow external libc to allow native posix to be used for unit test
    	# The cJSON library is using snprintf with floats. We therefore need to
    	# enable NEWLIB_LIBC_FLOAT_PRINTF to ensure that these are handled correctly.
    	depends on (NEWLIB_LIBC && NEWLIB_LIBC_FLOAT_PRINTF) || EXTERNAL_LIBC || PICOLIBC

    So, I use the Newlib library:

    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_NANO=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

    Once you have those set and the code is compiling fine, you should be able to start including cJSON without any extra setup.

    #include <cJSON.h>

    From there, you can use the library as intended. However, one last note is the memory heap for the Newlib library. You will need to make sure that your heap is big enough for your code and cJSON to work properly. If your getting exceptions about running out of memory, then make sure the following config is large enough.

    CONFIG_HEAP_MEM_POOL_SIZE=8192

  • FYI - I mocked up quick samples to show how I parse JSON and create the JSON strings. I didn't test these, but it should get you started.

    Create JSON String

    static bool sample_create_json(void)
    {
        // 1 - Create the root object
        cJSON *root = cJSON_CreateObject();
    
        if (!root)
        {
            printk("Unable to create root CJSON object.\n");
            return false;
        }
    
        // 2 - Add items
        cJSON *numberItem = cJSON_AddNumberToObjectCS(root, "name", 123);
    
        if (!numberItem)
        {
            printk("Unable to create JSON object.\n");
            cJSON_Delete(root);
            return false;
        }
    
        // Add other values as needed
    
        // 3 - Create the JSON string
        char *json = cJSON_PrintUnformatted(root);
    
        if (!json)
        {
            printk("Unable to create JSON string.\n");
            cJSON_Delete(root);
            return false;
        }
    
        // 4 - Do something with the JSON that was created
    
        // 5 - Always free the memory that was allocated.
        cJSON_Delete(root);
        return true;
    }
    

    Parse JSON String

    static bool sample_parse_json(const char *json)
    {
        __ASSERT_NO_MSG(json);
    
        // 1 - Parse the JSON
        cJSON *root = cJSON_Parse(json);
    
        // 2 - Verify it was parsed correctly
        if (!root)
        {
            const char *error = cJSON_GetErrorPtr();
    
            if (error)
            {
                printk("JSON Parse Error: %s\n", error);
            }
    
            return false;
        }
    
        // 3 - Do something with the parsed data
        for (cJSON *item = root; item; item = item->next)
        {
            const cJSON *child = item->child;
    
            while (child)
            {
                if (cJSON_IsNumber(child))
                {
                    // Process number
                }
                else if (cJSON_IsString(child))
                {
                    // Process string
                }
                else if (cJSON_IsArray(child))
                {
                    // Process array
                }
                else
                {
                    // Etc...
                }
    
                child = child->next;
            }
        }
    
        // 5 - Always free the memory that was allocated.
        cJSON_Delete(root);
        return true;
    }

  • This looks like really good info thanks - it'll be a few days before I get to work with - will let you know Slight smile

Related