Keil環境下Jansson解析庫的使用——基於STM32F103

前言

之前我曾經寫過幾個JSON解析庫的使用方法:

對於嵌入式開發,比較常用的就是cJSON解析庫了,但是使用這個庫對內存開銷比較大,需要大量使用malloc和free進行動態內存分配和釋放。對於單片機這種資源短缺的芯片來說,簡直是太喫力了。使用STM32等單片機,不能解析多層JSON時,還需要調大堆棧。

今天來了解一下一個和cJSON非常類似的解析庫——Jansson的使用,支持解析和構建JSON字符串,不需要動態分配內存,使用方法和cJSON幾乎一樣。

本文以Keil環境下的Jansson爲例,介紹多種不同格式的JSON字符串解析。

示例工程下載:whik1194-JanssonDemo.rar

Jansson的安裝

Jansson的安裝非常簡單,到Keil官網下載一個Jansson的Pack包即可:
Keil.Jansson.1.0.0.pack,點擊直接下載。

安裝完成之後,如果要在當前項目中添加Jansson解析庫,在Keil中勾選上Jansson即可,選擇完成之後,在當前工程下會出現兩個文件:jansson_CM3LE.libjansson_config.c在這裏插入圖片描述
在要使用的文件中包含頭文件:#include <jansson.h>

爲了方便調試,自定義實現了一個串口格式化輸出函數:LOG1。

void LOG1(char *fmt,...)
{
	unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	
	while(*pStr != 0)
	{
		while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
		USART_SendData(USART1, *pStr++);
	}
}

示例1:純鍵值對

JSON字符串,包括字符串、整形和布爾類型三種類型的鍵值對:

{
	"status": true,
	"age": 20,
	"name": "whik1194",
	"blog": "https://blog.csdn.net/whik1194",
	"wechat": "mcu149"
}

解析函數:


uint8_t Jansson1_Demo(void)
{
    const char *text = "{\"status\":true,\"age\":20,\"score\":78.4,\"name\":\"whik1194\",\"blog\":\"https://blog.csdn.net/whik1194\",\"wechat\":\"mcu149\"}";
    
    json_error_t error;
    json_t *root;
    json_t *status;
    
    char *name, *blog, *wechat;
    int age;
    double score;
    
    root = json_loads((const char*)text, 0, &error); 
    if(json_is_object(root))
    {
        LOG1("root format correct\r\n");
        
        /* string 類型的解析 */
        name = (char *)json_string_value(json_object_get(root, "name"));
        blog = (char *)json_string_value(json_object_get(root, "blog"));
        wechat = (char *)json_string_value(json_object_get(root, "wechat"));
        
        LOG1("name: %s\r\n", name);
        LOG1("blog: %s\r\n", blog);
        LOG1("wechat: %s\r\n", wechat);
        
        /* int 類型的解析 */
        age = json_integer_value(json_object_get(root, "age"));
        LOG1("age: %d\r\n", age);
        
        /* double 類型的解析 */
        score = json_real_value(json_object_get(root, "score"));
        LOG1("score: %.1f\r\n", score);
        
        /* bool 類型的解析 */
        status = json_object_get(root, "status");
        if(json_is_true(status))
            LOG1("status: true\r\n");
        else if(json_is_false(status))
            LOG1("status: false\r\n");
    }
    else
    {
        printf("root format error:%d-%s\r\n", error.line, error.text);
        return 1;
    }
    return 0;
}   

運行結果:
在這裏插入圖片描述

示例2:鍵的值是一個對象

JSON字符串,其中result鍵的值是一個JSON對象,包括幾組鍵值對:

{
	"success": "1",
	"result": {
		"timestamp": "1592640249",
		"datetime_1": "2020-06-20 16:04:09",
		"week_1": "6",
		"week_2": "Saturday"
	}
}

解析函數:

uint8_t Jansson2_Demo(void)
{
    const char *text = "{\"success\":\"1\",\"result\":{\"timestamp\":\"1592640249\",\"datetime_1\":\"2020-06-20 16:04:09\",\"week_1\":\"6\",\"week_2\":\"Saturday\"}}";
    json_error_t error;
    json_t *root;
    json_t *result;
    
    char *success;
    char *timestamp;
    char *datetime_1;
    char *week_1;

    root = json_loads((const char*)text, 0, &error); 
    if(json_is_object(root))
    {
        LOG1("root format correct\r\n");
        success = (char *)json_string_value(json_object_get(root, "success"));
        LOG1("success:%s\r\n", success);
        
        result = json_object_get(root, "result");
        if(json_is_object(result))
        {
            timestamp = (char *)json_string_value(json_object_get(result, "timestamp"));
            datetime_1 = (char *)json_string_value(json_object_get(result, "datetime_1"));
            week_1 = (char *)json_string_value(json_object_get(result, "week_1"));
            
            LOG1("timestamp:%s\r\n", timestamp);
            LOG1("datetime_1:%s\r\n", datetime_1);
            LOG1("week_1:%s\r\n", week_1);
        }
        else 
        {
            LOG1("reuslt format error\r\n");
            return 1;
        }
    }
    else
    {
        LOG1("root format error:%d-%s\r\n", error.line, error.text);
        return 1;
    }
    return 0;
}

運行結果:
在這裏插入圖片描述

示例3:鍵的值是一個數組

JSON字符串,鍵的值是一個JSON數組,包含兩個JSON對象:

{
	"location": [{
		"name": "Faye",
		"address": "Beijing"
	}, {
		"name": "Andy",
		"address": "ShangHai"
	}, {
		"name": "Lisa",
		"address": "ShenZhen"
	}],
	"time": "2018-11-17"
}

解析函數:

uint8_t Jansson3_Demo(void)
{
    const char *text = "{\"location\":[{\"name\":\"Faye\",\"address\":\"Beijing\"},{\"name\":\"Andy\",\"address\":\"ShangHai\"},{\"name\":\"Lisa\",\"address\":\"ShenZhen\"}],\"time\":\"2018-11-17\"}";
   
    json_error_t error;
    json_t *root;
    json_t *location_arr;
    json_t *location;
    
    char *name, *address;
    char *time;
    int idx;
    
    root = json_loads((const char*)text, 0, &error); 
    if(json_is_object(root))
    {
        LOG1("root format correct\r\n");
        time = (char *)json_string_value(json_object_get(root, "time"));
        location_arr = json_object_get(root, "location");
        if(json_is_array(location_arr))
        {
            for(idx = 0; idx < json_array_size(location_arr); idx++)
            {
                location = json_array_get(location_arr, idx);
                name = (char *)json_string_value(json_object_get(location, "name"));
                address = (char *)json_string_value(json_object_get(location, "address"));
                LOG1("%d: %s-%s\r\n", idx, name, address);
            }
        }
    }
    else
    {
        LOG1("root format error:%d-%s\r\n", error.line, error.text);
        return 1;
    }
    return 0;
}

運行結果:
在這裏插入圖片描述

注意

如果出現解析失敗,或者解析錯誤,可以嘗試增加Heap_Size大小:
在這裏插入圖片描述

不知道是不是編碼的問題,Jansson並不支持含有中文的JSON字符串解析,會報格式錯誤。

示例工程下載:whik1194-JanssonDemo.rar

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章