C语言Json

  1. 背景
    网上有开源的cJSON.c源码,cJSON.c 里面使用的动态内存,比较适合运行操作系统的平台。
    如果是单片机裸机的情况下,cJSON.c 比较容易出现内存泄漏,并且资源有限制。于是写了个简单的,对数组进行解析的json。有些情况没有考虑,可能会出现一些问题,有空再完善。
    getStringValue、getNumberString、getNumberStrInt、getNumberStrFloat、getStrIntValue、getStrFloatValue、getStrFloatIntDeci 这些函数的返回值是找到的键值后面的字符指针或者是NULL;目前只能是按顺序进行解析。

  2. 程序

//============================================================================
// Name        : myJson.cpp
// Author      : z
// Version     :
// Copyright   :
// Description :
//============================================================================


#include <stdlib.h>
#include <stdio.h>
#include <string.h>

enum JsonType_t{
	IsArray,
	IsString,
	IsRoot,
	IsSubObject
};

struct cJson_t{
	char *data;
	char * array;

	int dataLength;
	int arraySize;

	enum JsonType_t type;
	int pushSize;
	int insertPosi;

	char backup[200];
};


struct cJson_t  cJsonCreateObject(char * array,const int arraySize,struct cJson_t * root,enum JsonType_t type )
{

	int offset;
	if(type == IsRoot){
	if(root == NULL)
		return *root;

	if((root) == NULL)
		return *root;

	if(array == NULL)
		return *root;
	}

	if(type == IsRoot)
	{
		root->array = array;
		root->arraySize = arraySize;

		root->data = root->array;

		root->data[0] = '{';
		root->data[1] = '}';
		root->data[2] = '\0';

		root->dataLength = 2;

		root->insertPosi = 0;
		root->pushSize = 1;
	}
	else if(type == IsSubObject)
	{

		root->pushSize = root->dataLength - root->insertPosi -1;
		root->backup[root->pushSize] = 0;
		memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);

		if(
					((root->data[root->insertPosi] == '['))
					||
					((root->data[root->insertPosi] == '{'))
			)
		{
			memcpy(root->backup,root->data+root->insertPosi,root->pushSize);
			offset = sprintf(root->data+root->insertPosi,"{}%s",root->backup);

			root->dataLength =  root->insertPosi +1 + offset;
			offset -= root->pushSize;
			root->insertPosi += offset;
		}
		else
		{
			if ((root->data[root->insertPosi] != '\"'))
			{
				memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);
				offset = sprintf(root->data+root->insertPosi+1,",{}%s",root->backup);

				root->dataLength =  root->insertPosi +1 + offset;
				offset -= root->pushSize;
				root->insertPosi += offset -1;
			}
			else
			{
				if ((root->data[root->insertPosi+1] != '}') )
				{
					memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);
					offset = sprintf(root->data+root->insertPosi+1,",{}%s",root->backup);
					root->dataLength =  root->insertPosi +1 + offset;
					offset -= root->pushSize;
					root->insertPosi += offset -1;
				}
				else
				{
					memcpy(root->backup,root->data+root->insertPosi+2,root->pushSize);
					offset = sprintf(root->data+root->insertPosi+2,",{}%s",root->backup);

					root->dataLength =  root->insertPosi +2 + offset;
					offset -= root->pushSize;
					root->insertPosi += offset+1;
				}
			}

		}

	}

	root->type = type;

	return *root;
}


void cJsonAddStringItemToObject(struct cJson_t *root,const char *key, const char *value)
{
	int offset = 0;
	if(root == NULL)
		return;

	if(key == NULL)
		return;

	if(value == NULL)
		return;

	int keyLen = strlen(key);
	int valueLen = strlen(value);
	if((keyLen+valueLen)>(root->arraySize - root->dataLength - 5))//5 bytes for reserved
		return ;

	offset = keyLen+valueLen;

	root->pushSize = root->dataLength - root->insertPosi -1;
	root->backup[root->pushSize] = 0;
	memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);

	if(
			(root->data[root->insertPosi] == '[')||
			(root->data[root->insertPosi] == '{')
	)
	{
		offset = sprintf(root->data+root->insertPosi+1,"\"%s\":\"%s\"%s",key,value,root->backup);
	}
	else
	{
		offset = sprintf(root->data+root->insertPosi+1,",\"%s\":\"%s\"%s",key,value,root->backup);
	}

	root->dataLength =  root->insertPosi +1 + offset;
	offset -= root->pushSize;
	root->insertPosi += offset;

}


void cJsonAddIntItemToObject(struct cJson_t *root,const char *key,  const int number)
{
	int offset = 0;
	char value[20];

	memset(value,0,sizeof(value));
	sprintf(value,"%d",number);

	if(root == NULL)
		return;

	if(key == NULL)
		return;

	if(value == NULL)
		return;

	int keyLen = strlen(key);
	int valueLen = strlen(value);
	if((keyLen+valueLen)>(root->arraySize - root->dataLength - 5))//5 bytes for reserved
		return ;

	offset = keyLen+valueLen;

	root->pushSize = root->dataLength - root->insertPosi -1;
	root->backup[root->pushSize] = 0;
	memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);

	if(
			(root->data[root->insertPosi] == '[')||
			(root->data[root->insertPosi] == '{')
	)
	{
		offset = sprintf(root->data+root->insertPosi+1,"\"%s\":%s%s",key,value,root->backup);
	}
	else
	{
		offset = sprintf(root->data+root->insertPosi+1,",\"%s\":%s%s",key,value,root->backup);
	}

	root->dataLength =  root->insertPosi +1 + offset;
	offset -= root->pushSize;
	root->insertPosi += offset;
}

void cJsonAddFloatItemToObject(struct cJson_t *root,const char *key,  const float number)
{
	int offset = 0;
	char value[20];

	memset(value,0,sizeof(value));
	sprintf(value,"%f",number);

	if(root == NULL)
		return;

	if(key == NULL)
		return;

	if(value == NULL)
		return;

	int keyLen = strlen(key);
	int valueLen = strlen(value);
	if((keyLen+valueLen)>(root->arraySize - root->dataLength - 5))//5 bytes for reserved
		return ;

	offset = keyLen+valueLen;

	root->pushSize = root->dataLength - root->insertPosi -1;
	root->backup[root->pushSize] = 0;
	memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);

	if(
			(root->data[root->insertPosi] == '[')||
			(root->data[root->insertPosi] == '{')
	)
	{
		offset = sprintf(root->data+root->insertPosi+1,"\"%s\":%s%s",key,value,root->backup);
	}
	else
	{
		offset = sprintf(root->data+root->insertPosi+1,",\"%s\":%s%s",key,value,root->backup);
	}

	root->dataLength =  root->insertPosi +1 + offset;
	offset -= root->pushSize;
	root->insertPosi += offset;
}

void cJsonAddStrIntItemToObject(struct cJson_t *root,const char *key, const int number)
{
	char value[20];
	memset(value,0,sizeof(value));
	sprintf(value,"%d",number);

	cJsonAddStringItemToObject(root,key,value);
}

void cJsonAddStrFloatItemToObject(struct cJson_t *root,const char *key, const float number)
{
	char value[20];
	memset(value,0,sizeof(value));
	sprintf(value,"%f",number);

	cJsonAddStringItemToObject(root,key,value);
}

struct cJson_t  cJsonAddArrayToObject(struct cJson_t *root, const char *arrayName)
{
	int offset = 0;
	if(root == NULL)
		return *root;

	if(arrayName == NULL)
		return *root;

	int nameSize = strlen(arrayName);

	if((nameSize)>(root->arraySize - root->dataLength - 5))//5 bytes for reserved
		return *root;

	root->type = IsArray;

	root->pushSize = root->dataLength - root->insertPosi -1;
	root->backup[root->pushSize] = 0;
	memcpy(root->backup,root->data+root->insertPosi+1,root->pushSize);

	char * p_d = strstr(root->data+root->insertPosi,"]");
	if( p_d != NULL)
	{
		root->insertPosi = p_d - root->data;

		root->pushSize = root->dataLength - root->insertPosi -1;
		root->backup[root->pushSize] = 0;
	}

	if(root->data[root->insertPosi] == ']')
	{
		offset = sprintf(root->data+root->insertPosi+1,",\"%s\":[]%s",arrayName,root->backup);
	}
	else if(root->data[root->insertPosi] != '\"')
	{
		offset = sprintf(root->data+root->insertPosi+1,"\"%s\":[]%s",arrayName,root->backup);
	}
	else
	{
		offset = sprintf(root->data+root->insertPosi+1,",\"%s\":[]%s",arrayName,root->backup);
	}

	root->dataLength =  root->insertPosi +1 + offset;
	offset -= root->pushSize;
	root->insertPosi += offset-1;

	return  *root;
}

/* parse hexadecimal number */
unsigned int parseHex(const unsigned char * const input)
{
    unsigned int h = 0;
    char i = 0;
    const char numLen = strlen((char *)input);
    for (i = 0; i < numLen; i++)
    {
        /* parse digit */
        if ((input[i] >= '0') && (input[i] <= '9'))
        {
            h += (unsigned int) input[i] - '0';
        }
        else if ((input[i] >= 'A') && (input[i] <= 'F'))
        {
            h += (unsigned int) 10 + input[i] - 'A';
        }
        else if ((input[i] >= 'a') && (input[i] <= 'f'))
        {
            h += (unsigned int) 10 + input[i] - 'a';
        }
        else /* invalid */
        {
            return 0;
        }

        if (i < numLen-1)
        {
            /* shift left to make place for the next nibble */
            h = h << 4;
        }
    }

    return h;
}

unsigned int parseInteger(const char * const input)
{
    unsigned int num = 0;
    unsigned int sum = 0;
    char i = 0;
    const char numLen = strlen((char *)input);

    for (i = 0; i < numLen; i++)
    {
        /* parse digit */
        if ((input[i] >= '0') && (input[i] <= '9'))
        {
        	num =  (unsigned int) input[i] - '0';
        }
        else /* invalid */
        {
            return 0;
        }

        if (i != 0)
        {
        	sum *= 10;
        }
        sum += num;
    }

    return sum;
}
char * getStringValue(const char * data,const char *key,char *value)
{
	char *p = NULL;
	char *p_start = NULL;
	int len;

	p = (char *)data;

	p_start = strstr(p,key);

	if(p_start == NULL)
		return NULL;

	p_start += strlen(key);

	//key second \"
	p = p_start;
	p_start = strstr(p,"\"");

	if(p_start == NULL)
		return NULL;

	p = p_start+1;

	//value first \"
	p_start = strstr(p,"\"");

	if(p_start == NULL)
		return NULL;
	p = p_start+1;

	//value second \"
	p_start = strstr(p,"\"");
	if(p_start == NULL)
		return NULL;

	len = p_start - p;

	if(len>20)// maybe next key
		return NULL;

	memcpy(value,p,len);
	value[len] = 0;

	p = p_start+1;

	return  p;
}

char * getNumberString(const char * data,const char *key,char *value)
{
	char *p = NULL;
	char *p_start = NULL;
	int len;

	p = (char *)data;

	p_start = strstr(p,key);

	if(p_start == NULL)
		return NULL;

	p_start += strlen(key);

	//key second \"
	p = p_start;
	p_start = strstr(p,"\"");

	if(p_start == NULL)
		return NULL;

	p = p_start+1;

	//value first :
	p_start = strstr(p,":");

	if(p_start == NULL)
		return NULL;
	p = p_start+1;

	//value second ,
	p_start = strstr(p,",");
	if(p_start == NULL)
		return NULL;

	len = p_start - p;

	if(len>20)// maybe next key
		return NULL;

	memcpy(value,p,len);
	value[len] = 0;

	p = p_start+1;

	return  p;
}

char * getNumberStrInt(const char * data,const char *key,int *value)
{
	char str[20];
	memset(str,0,sizeof(str));
	char * p = NULL;
	char * p_end = NULL;
	int number;

	p_end = getNumberString(data,key,str) ;
	if( p_end == NULL)
		return NULL;

	p = strstr(str,"0x") ;

	if( p == NULL )
		p = strstr(str,"0X") ;

	if(p == NULL)//no hex
	{
		p = strstr(str,"-") ;
		if( p != NULL )
		{
			number = (int)parseInteger((const char *)(p+1));
			number = (0-number);
		}
		else{
			number = (int)parseInteger((const char *)str);
		}
	}
	else
	{
		number = (int)parseHex((const unsigned char *)p+2);
	}

	*value = number;

	return p_end;
}

char * getStrIntValue(const char * data,const char *key,int *value)
{
	char str[20];
	memset(str,0,sizeof(str));
	char * p = NULL;
	char * p_end = NULL;
	int number;

	p_end = getStringValue(data,key,str) ;
	if( p_end == NULL)
		return NULL;

	p = strstr(str,"0x") ;

	if( p == NULL )
		p = strstr(str,"0X") ;

	if(p == NULL)//no hex
	{
		p = strstr(str,"-") ;
		if( p != NULL )
		{
			number = (int)parseInteger((const char *)(p+1));
			number = (0-number);
		}
		else{
			number = (int)parseInteger((const char *)str);
		}

	}
	else
	{
		number = (int)parseHex((const unsigned char *)p+2);
	}

	*value = number;

	return p_end;
}


char * getNumberStrFloatIntDeci(const char * data,const char *key,int *integer,int *decimal)
{
	char str[20];
	memset(str,0,sizeof(str));
	char * p = NULL;
	char * p_end = NULL;
	char * p_start = NULL;
	int inte;
	int deci;

	p_end = getNumberString(data,key,str) ;
	if( p_end == NULL)
		return NULL;
	p = p_end;

	p_start = strstr(str,"-");
	if(p_start == NULL)
		p = str;
	else
		p = p_start+1;


	p_start = strstr(p,".");
	if(p_start == NULL)// no decimal
	{
		inte = (int)parseInteger((const char *)p);
		deci = 0;
	}
	else
	{
		*p_start = 0;
		inte = (int)parseInteger((const char *)p);
		*p_start = '.';
		deci = (int)parseInteger((const char *)p_start+1);
	}

	*decimal = deci;

	if(p != str)
		inte = 0-inte;

	*integer = inte;

	return p_end;
}


char * getNumberStrFloat(const char * data,const char *key,float *value)
{
	char * p = NULL;

	int inte;
	int deci;
	float number = 0;

	p = getNumberStrFloatIntDeci(data,key,&inte,&deci);
	if( p == NULL)
		return NULL;

	number = deci;
	deci *= 10;

	while(deci/10)
	{
		deci /= 10;
		number *= 0.1;
	}

	if(inte>0)
	{
		number +=  inte;
	}
	else
	{
		inte = 0 - inte;
		number +=  inte;
		number = 0 - number;
	}
	*value = number;
	return p;
}

char * getStrFloatIntDeci(const char * data,const char *key,int *integer,int *decimal)
{
	char str[20];
	memset(str,0,sizeof(str));
	char * p = NULL;
	char * p_end = NULL;
	char * p_start = NULL;
	int inte;
	int deci;

	p_end = getStringValue(data,key,str) ;
	if( p_end == NULL)
		return NULL;
	p = p_end;

	p_start = strstr(str,"-");
	if(p_start == NULL)
		p = str;
	else
		p = p_start+1;

	p_start = strstr(p,".");
	if(p_start == NULL)// no decimal
	{
		inte = (int)parseInteger((const char *)p);
		deci = 0;
	}
	else
	{
		*p_start = 0;
		inte = (int)parseInteger((const char *)p);
		*p_start = '.';
		deci = (int)parseInteger((const char *)p_start+1);
	}

	*decimal = deci;

	if(p != str)
		inte = 0-inte;

	*integer = inte;

	return p_end;
}

char * getStrFloatValue(const char * data,const char *key,float *value)
{
	char * p = NULL;

	int inte;
	int deci;
	float number = 0;

	p = getStrFloatIntDeci(data,key,&inte,&deci);

	if( p == NULL)
		return NULL;

	number = deci;
	deci *= 10;
	while(deci/10)
	{
		deci /= 10;
		number *= 0.1;
	}

	if(inte>0)
	{
		number +=  inte;
	}
	else
	{
		inte = 0 - inte;
		number +=  inte;
		number = 0 - number;
	}

	*value = number;

	return p;
}




int main() {

	char data[1000];

	struct cJson_t root;
	struct cJson_t * pRoot = &root;
	struct cJson_t  arrayRoot;
	struct cJson_t  subObj;

	root = cJsonCreateObject(data,sizeof(data),pRoot,IsRoot);

	cJsonAddStringItemToObject(pRoot,"token","200513");
	cJsonAddStringItemToObject(pRoot,"time","2020-05");
	cJsonAddStringItemToObject(pRoot,"data_row","single");
	cJsonAddIntItemToObject(pRoot,"data_row1",  123);
	cJsonAddFloatItemToObject(pRoot,"data_row2",12.3);
	cJsonAddStrIntItemToObject(pRoot,"data_row3",  124);
	cJsonAddStrFloatItemToObject(pRoot,"data_row4",  13.3);


	arrayRoot = cJsonAddArrayToObject(pRoot,"body");
	cJsonAddStringItemToObject(&arrayRoot,"dev","ZX");

	subObj = cJsonCreateObject(NULL,0,&arrayRoot,IsSubObject);
	cJsonAddStringItemToObject(&subObj,"name","TmpA");
	cJsonAddStringItemToObject(&subObj,"val","58");
	cJsonAddStringItemToObject(&subObj,"quality","-10");

	subObj = cJsonCreateObject(NULL,0,&subObj,IsSubObject);
	cJsonAddStringItemToObject(&subObj,"name","TH");
	cJsonAddStringItemToObject(&subObj,"val","0xFFFF");
	cJsonAddStringItemToObject(&subObj,"quality","100");

	subObj = cJsonCreateObject(NULL,0,&subObj,IsSubObject);
	cJsonAddStringItemToObject(&subObj,"name","TA");
	cJsonAddStringItemToObject(&subObj,"val","-102.235");
	cJsonAddStringItemToObject(&subObj,"quality","0");

#if 1
	arrayRoot = cJsonAddArrayToObject(&subObj,"bo2");
	cJsonAddStringItemToObject(&arrayRoot,"dev","Z");

	subObj = cJsonCreateObject(NULL,0,&arrayRoot,IsSubObject);
	cJsonAddStringItemToObject(&subObj,"name","TA");
	cJsonAddStringItemToObject(&subObj,"val","1");
	cJsonAddStringItemToObject(&subObj,"quality","1");

	subObj = cJsonCreateObject(NULL,0,&subObj,IsSubObject);
	cJsonAddStringItemToObject(&subObj,"name","2");
	cJsonAddStringItemToObject(&subObj,"val","2");
	cJsonAddStringItemToObject(&subObj,"quality","2");
#endif

	printf("data is \n%s\n",data);

	//parse json data
	char value[10];
	int intValue,deciValue;
	float flValue;
	char *p_data = NULL;
	char *p = NULL;

	p_data = getStringValue(data,"token",value);
	if( p_data != NULL)
		printf("getStringValue is %s\n",value);

	p_data = getNumberString(data,"data_row1",value);
	if( p_data != NULL)
		printf("getNumberString is %s\n",value);



	p_data = getNumberStrInt(data,"data_row1",&intValue);
	if( p_data != NULL)
		printf("getNumberStrInt is %d\n",intValue);

	p_data = getNumberString(data,"data_row2",value);
	if( p_data != NULL)
		printf("getNumberString is %s\n",value);

	p_data = getNumberStrFloat(data,"data_row2",&flValue);
	if( p_data != NULL)
		printf("getNumberStrFloat is %f\n",flValue);


	p_data = getStrIntValue(p_data,"val",&intValue);
	if( p_data != NULL)
		printf("getStrIntValue is %d\n",intValue);

	p_data = getStrIntValue(p_data,"quality",&intValue);
	if( p_data != NULL)
		printf("getStrIntValue is %d\n",intValue);

	p_data = getStrIntValue(p_data,"val",&intValue);
	if( p_data != NULL)
		printf("getStrIntValue is %d\n",intValue);

	p_data = getStrIntValue(p_data,"quality",&intValue);
	if( p_data != NULL)
		printf("getStrIntValue is %d\n",intValue);

	p = p_data;
	p_data = getStrFloatValue(p_data,"val",&flValue);
	if( p_data != NULL)
		printf("getStrFloatValue is %f\n",flValue);

	p_data = p ;
	p_data = getStrFloatIntDeci(p_data,"val",&intValue,&deciValue);
	if( p_data != NULL)
		printf("getStrFloatIntDeci is %d.%d\n",intValue,deciValue);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43479963/article/details/106797396
今日推荐