c環境下Json字符串的解析

c環境下Json字符串的解析

對於Json字符串,最常見的方式就是一個一個的鍵值對被一個大的Obect包裹着,但是往往由於實際項目需要json字符串不可能保持最簡單的形式來進行數據傳輸。

以最近一個小項目爲例:

從手機客戶端組織數據,形成Json字符串的主要形式有如下幾種:

1. char *xjson = "[{\"TotalNum\":123},{\"Tvstate\":2},{\"ProgrameId\":014000789},{\"request\":1004}]";

2.char *xjson = "{\"TotalNum\":\"123\",\"name\":\"mao\",\"request\":1004}";

3.char *xjson = "{\"ToIndex\":\"99\",\"FromIndex\":\"0\",\"request\":\"0\"}";

4.char *xjson = "{\"array\":[{\"TotalNum\": 123,\"Tvstate\": \"2\"}],\"request\": 44}";

5.char *xjson = "{\"array\":[{\"TotalNum\": 123},{\"Tvstate\": \"2\"}],\"request\": \"44\"}";

6.char *xjson = "{\"TvSate\":0,\"FavMark\":64,\"FavGroupId\":\"\",\"array\":[{\"ProgrameId\": \"4334\"},{\"ProgrameId\":4334}],\"TotalNum\":3,\"request\":1004}";

7.char *xjson =  "{\"array\":[{\"data\":\"M040\"},{\"uuid\":\"860806027379485-38:BC:1A:87:E0:26\"}],\"request\":\"998\"}";

8.char *xjson = "{\"request\":1004}";

需要在機頂盒端接收到手機客戶端發送過來的json字符串數據,並且將其解析出來存放到各自對應的已經實現定義好的結構體中。

大致的過程就是:

APK -------發送Json字符串給------>服務器端------解析json字符串到------>C結構體

那麼具體的需求就是:

在服務器端的解析函數必須能夠適配解析不同的json字符串。在不知道每一個json字符串的鍵值對的情況下,取出該json字符串的鍵值,存放在c結構體中,並且將這些結構體以鏈表的形式存放在內存中。

在c語言環境下有一個開源的cJSON庫,其中封裝好了一些列對json數據進行操作的函數。

cJSON結構體定義如下:

typedefstruct cJSON {

structcJSON *next,*prev;

struct cJSON *child;

int type;

char * valuestring;

int valueint;

double valuedouble;

char *string;

}cJSON;

其中type取值共有7中,分別是:

#define cJSON_False 0

#define cJSON_True 1

#define cJSON_NULL 2

#define cJSON_Number 3

#define cJSON_String 4

#define cJSON_Array 5

#define cJSON_Object 6

考慮到我們在客戶端組織起來的json字符串主要由Number、String、Array、Object組成,因此採用多重嵌套swicth進行解析。當然也可以使用遞歸進行解析,但是由於遞歸在項目開發中特別是嵌入式開發中一般不建議使用,所以這次並沒有採用遞歸的方法進行解析。

具體的解析代碼

其中涉及到的主要函數爲:

解析的入口函數:parse_cjson_to_json_root()

解析子json結構體爲Array的函數:parse_json_sub_type_array();

解析子json結構體爲Object的函數:parse_json_sub_type_object();

解析子json結構體爲Number和String的函數:parse_json_sub_type_others();


主要代碼如下:

<pre name="code" class="html">#include <stdio.h>
#include <string.h>
#include "usifext.h"
#include "json_parser.h"
#include "cJSON.h"
#include "gs_os.h"

void parse_json_sub_type_others(cJSON** psub, json_node_info** tag_node, json_root_info** proot_node, json_node_info** tag_point,
        json_attr_info** tag_attr_node, int type)
{

	int text_int = 0;
	char *text_string = "";

	(*tag_node) = (json_node_info *)malloc(sizeof(json_node_info));
	memset((*tag_node)->tag_name, 0, sizeof((*tag_node)->tag_name));
	memset((*tag_node)->tag_text, 0, sizeof((*tag_node)->tag_text));

	char *tag = (*psub)->string;

	if (cJSON_Number == type)
	{
		text_int = (*psub)->valueint;
	}
	else
	{
		text_string = (*psub)->valuestring;
	}

	if (strcmp(tag, JSON_HEADER_CONTROL_TAG) != 0)
	{
		strcpy((*tag_node)->tag_name, tag);
		if (cJSON_Number == type)
		{
			ITOA((*tag_node)->tag_text, text_int);
		}
		else
		{
			strcpy((*tag_node)->tag_text, text_string);
		}
		(*tag_node)->next = NULL;

		if ((*proot_node)->next == NULL)
		{
			(*proot_node)->next = (*tag_node);
			(*tag_point) = (*tag_node);
		}
		else
		{
			(*tag_point)->next = (*tag_node);
			(*tag_point) = (*tag_node);
		}
	}
	else
	{
		(*tag_attr_node) = (json_attr_info*)malloc(sizeof(json_attr_info));
		memset((*tag_attr_node)->name, 0, sizeof((*tag_attr_node)->name));
		memset((*tag_attr_node)->value, 0, sizeof((*tag_attr_node)->value));
		strcpy((*tag_attr_node)->name, tag);

		if (cJSON_Number == type)
		{
			ITOA((*tag_attr_node)->value, text_int);
		}
		else
		{
			strcpy((*tag_attr_node)->value, text_string);
		}
		(*proot_node)->attr_list = (*tag_attr_node);

	}

}

void parse_json_sub_type_array(cJSON** psub, json_node_info** tag_node, json_root_info** proot_node, json_node_info** tag_point,
        json_attr_info** tag_attr_node)
{

	int j = 0;
	for (j = 0; j < cJSON_GetArraySize((*psub)); j++)
	{
		cJSON *psub_sub = cJSON_GetArrayItem((*psub), j);

		if (psub_sub->type == cJSON_Object)
		{
			parse_json_sub_type_obj(&psub_sub, tag_node, proot_node, tag_point, tag_attr_node);
		}
	}

}

void parse_json_sub_type_obj(cJSON** psub, json_node_info** tag_node, json_root_info** proot_node, json_node_info** tag_point,
        json_attr_info** tag_attr_node)
{

	int j = 0;
	for (j = 0; j < cJSON_GetArraySize((*psub)); j++)
	{
		cJSON *psub_sub = cJSON_GetArrayItem((*psub), j);
		parse_json_sub_type_others(&psub_sub, tag_node, proot_node, tag_point, tag_attr_node, psub_sub->type);
	}

}

int parse_cjson_to_json_root(cJSON *pjson, json_root_info *proot_node)
{
	int i = 0;
	int size = 0;

	json_node_info* tag_node;
	json_attr_info* tag_attr_node;
	json_node_info* tag_point = NULL;

	if (NULL == proot_node)
	{
		return -1;
	}

	if (NULL == pjson)
	{
		return -1;
	}

	(proot_node)->next = NULL;
	size = cJSON_GetArraySize(pjson);
	for (i = 0; i < size; i++)
	{
		cJSON *psub = cJSON_GetArrayItem(pjson, i);
		switch (psub->type)
		{
			case cJSON_Array:
				parse_json_sub_type_array(&psub, &tag_node, &proot_node, &tag_point, &tag_attr_node);
				break;
			case cJSON_Object:
				parse_json_sub_type_obj(&psub, &tag_node, &proot_node, &tag_point, &tag_attr_node);
				break;
			case cJSON_String:
			case cJSON_Number:
				parse_json_sub_type_others(&psub, &tag_node, &proot_node, &tag_point, &tag_attr_node, psub->type);
				break;
			default:
				return -1;
		}

	}
	return 0;
}
其中涉及到一些自定義的函數, ITOA、GSOS_MALLOC().


int ITOA(char * str, unsigned long val)
{
	char *p;
	char *first_dig;
<span style="white-space:pre">	</span>char temp;
unsigned t_val;
int len = 0;
p = str;
first_dig = p;


do
{
t_val = (unsigned)(val % 0x0a);
val   /= 0x0a;
*p++ = (char)(t_val + '0');
len++;
}
while (val > 0);
*p-- = '\0';
do
{
temp = *p;
*p   = *first_dig;
*first_dig = temp;
--p;
++first_dig;
}
while (first_dig < p);
return len;
}

</pre><pre name="code" class="html">採用遞歸的方式更加簡單,主要函數和代碼如下:
int parse_json(cJSON * pJson,xml_root_info *proot_node)
{
    xml_node_info* tag_node;
xml_attr_info* tag_attr_node;
xml_node_info* tag_point = NULL;


    tag_node = (xml_node_info *) malloc(sizeof(xml_node_info));
    memset(tag_node->tag_name,0,sizeof(tag_node->tag_name));
    memset(tag_node->tag_text,0,sizeof(tag_node->tag_text));


    tag_attr_node = (xml_attr_info*) malloc(sizeof(xml_attr_info));
    memset(tag_attr_node->name,0,sizeof(tag_attr_node->name));
    memset(tag_attr_node->value,0,sizeof(tag_attr_node->value));


    tag_point = (xml_node_info *) malloc(sizeof(xml_node_info));

    if(NULL == pJson)
    {
        return -1;
    }
    printf(" pJson->type :%d\n", pJson->type);
    switch(pJson->type)
    {
        case cJSON_False :
            {
                char *value_string = pJson->string;
                int value_int = pJson->valueint;
                strcpy(tag_node->tag_name, value_string);


                //ITOA(tag_attr_node->value, value_int);
            }
            break;
        case cJSON_True :
            {
                char *value_string = pJson->string;
                int value_int = pJson->valueint;
                strcpy(tag_node->tag_name, value_string);
                //ITOA(tag_attr_node->value, value_int);
            }
            break;
        case cJSON_NULL :
            {
                printf("%s : NULL\n", pJson->string);
            }
            break;
        case cJSON_Number :
            {
                char *value_string = pJson->string;
                int value_int = pJson->valueint;


                if(strcmp(value_string, "request") != 0)
                {
strcpy(tag_node->tag_name, value_string);
itoa(value_int, tag_node->tag_text, 10);
tag_node->next = NULL;
if(count == 0)
{
proot_node->next = tag_node;
tag_point = tag_node;
count++;
}
else
{
tag_point = (proot_node)->next;
while(NULL != tag_point->next)
{
printf("up循環遍歷裏面\n");
tag_point = tag_point->next;
printf("down循環遍歷裏面\n");
 }
tag_point->next = tag_node;
tag_point = tag_node;
}
                }
                else
                {
strcpy(tag_attr_node->name, value_string);
itoa(value_int, tag_attr_node->value, 10);
proot_node->attr_list = tag_attr_node;
//proot_node->next=NULL;
                }
            }
            break;
        case cJSON_String :
            {
                char *value_string = pJson->string;
                char *pJsonString = pJson->valuestring;
                if(strcmp(value_string, "request") != 0)
                {
strcpy(tag_node->tag_name, value_string);
strcpy(tag_node->tag_text, pJsonString);
tag_node->next = NULL;
 if(count == 0)
{
proot_node->next = tag_node;
tag_point = tag_node;
count++;
printf("count_01:%d\n", count);
}
else
{
tag_point = (proot_node)->next;
while(NULL != tag_point->next)
{
printf("up循環遍歷裏面\n");
tag_point = tag_point->next;
printf("down循環遍歷裏面\n");
 }
tag_point->next = tag_node;
tag_point = tag_node;
}
                }
                else
                {
strcpy(tag_attr_node->name, value_string);
strcpy(tag_attr_node->value, pJsonString);


proot_node->attr_list = tag_attr_node;
                }
            }
            break;
        case cJSON_Array  :
        case cJSON_Object :
            {
                int iSize = cJSON_GetArraySize(pJson);
                int i = 0;
                printf("%s\n", NULL == pJson->string ? "" : pJson->string);
                for(i = 0; i < iSize; i++)
                {
                    cJSON * pSub = cJSON_GetArrayItem(pJson, i);
                    parse_json(pSub, proot_node);
                }
            }
            break;
        default :
            return -1;
            break;
    }
}


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