Encoding JSON array of an array of floats

Hi,

I'm developing Software for the nRF52840. I'm using NCS version 2.2.0 and Zephyr OS build v3.2.99-ncs1.

I try to encode a JSON message that will be send via MQTT.

I managed to encode, objects, strings and other primitives,

But now I'm blocked trying to encode a double array of floats.

The JSON message I'm trying to encode would be like this:

{"observations":[[3.0, 0.20],[5.0, 0.30],[4.5, 0.25]]}

I have tried to follow the JSON_OBJ_DESCR_ARRAY_ARRAY example, like in line 390 in "zephyr/data/json.h" but I think the example shown is for an array of an array of objects (not floats), and I could not manage to get the desired result, although I have tried with several options.

Could you please give me some advice? An example of JSON_OBJ_DESCR_ARRAY_ARRAY, for floats would be appreciated.

Thanks and regards,

Jordi.

Parents Reply Children
  • Hi Sigurd,

    It's OK, I finally make it.

    As JSON_TOK_FLOAT, can accept any formatted string, I first encode the double array of floats and then I lie the json_obj_token.start to point to that "fake" string.

    I insert a code example here:

    #include <stdlib.h>
    #include <kernel.h>
    #include <data/json.h>
    
    static float vector[3][2] = {
    	{2.34, 0.64},
    	{3.41, 0.67},
    	{2.56, 0.59}
    };
    
    struct json_data{
    	struct json_obj_token vector;
    	char arr_arr_floats[100];
    };
    
    static struct json_obj_descr parent_descr[] = {
    	JSON_OBJ_DESCR_PRIM(struct json_data, vector, JSON_TOK_FLOAT)
    };
    
    size_t encode_aray_array_float(float** data, size_t M, size_t N, char* buf_ini)
    {
    	char* buf = buf_ini;
    
    	*buf++ = '[';
    	for(int i = 0; i < M; i++){
    		*buf++ = '[';
    		for(int j = 0; j < N; j++){
    			gcvt(data[i][j], 6, buf);
    			while(*buf != '\0') buf++;
    			if(j < N - 1){
    				*buf++ = ',';
    			}
    		}
    		*buf++ = ']';
    		if(i < M - 1){
    			*buf++ = ',';
    		}
    	}
    	*buf++ = ']';
    	*buf = '\0';
    	return (buf - buf_ini);
    }
    
    int main()
    {
    	struct json_data data;
    
    	/** Prepare JSON data */
    	data.vector.length = encode_aray_array_float((float**)vector, 3, 2, data.arr_arr_floats);
    	data.vector.start = data.arr_arr_floats;
    
    	/** Encode the json obj */
    	char json[200];
    	int err = json_obj_encode_buf(parent_descr, ARRAY_SIZE(parent_descr), &data, json, sizeof(json));
    	printk("err = %d\n", err);
    	printk("%s\n", json);
    
    	while(1){
    		k_msleep(1000);
    	}
    }

    I wonder if there is a more elegant way to do it.

    I close the case, many thanks for your attention.

    Jordi.

  • Hi Jordi,

    Good to hear that you found JSON_TOK_FLOAT!

    I do not know if it runs faster, but it ups readability to use "sprintf":

    #include <zephyr/kernel.h>
    #include <stdio.h>
    
    static float vector[3][2] = {
        {2.34, 0.64},
        {3.41, 0.67},
        {2.56, 0.59}
    };
    
    
    void encode_aray_array_float(int M, int N, float data[M][N], char* buf_ini){
    
        sprintf(buf_ini, ""); // Initialize buf_init to be empty
        for(int m=0; m<M; m++){
            for(int n=0; n<N; n++){
                if(n==N-1){
                    sprintf(buf_ini, "%s [%.2lf];", buf_ini, data[m][n]);
                }
                else {
                    sprintf(buf_ini, "%s [%.2lf],", buf_ini, data[m][n]);
                }
            }
        }
    }
    
    
    void main(void)
    {
        char test_string[200];
        encode_aray_array_float(3, 2, vector, test_string);
        printk("%s\n", test_string);
    }
    

    and prj.conf:

    # To make sprintf work with floats
    CONFIG_NEWLIB_LIBC=y
    CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y
    
    # To make printk work with floats
    CONFIG_CBPRINTF_FP_SUPPORT=y
    

    Regards,
    Sigurd Hellesvik

Related