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