您的位置:首页 > Web前端 > JavaScript

单片机Json框架的实现

2016-01-28 23:42 931 查看

背景

月初写了一个简单的单片机json生成框架,目的是想为蓝牙开发板封装一套协议。加班了小一个月,终于有时间喘口气搞搞自己的东西了….回过头来看,发现很多不足之处,抽空进行了一些重构。主要修改了以下几个方面:

1.修改了基本的数据结构,统一抽象为 JsonPair 与 JsonObject,方便解析;

2.重新定义了内存管理模块,将结构存储与数据存储分开管理,这样方便根据不同的MCU进行相应调整;

3.重新实现了相应的方法

基本结构

上一篇文章中定义的结构比较混乱,虽然可以较为容易地实现json的生成,但是解析时就会使程序变得异常混乱,所以我将json结构重新抽取为

JsonPair和JsonObject,json数组就是若干JsonObject组成。

typedef struct _JsonPair{

char *key;
char *value;
int keyLength;
int valueLength;

struct _JsonObject **obj;
int jsonObjLength;

int valueType;

struct _JsonPair *next;
//struct _JsonPair *prev;

//char* (* setPair)(struct _JsonPair *this, char *key, char *value);
//char* (* getValue)(struct _JsonPair *this, char *key);
} JsonPair;

typedef struct _JsonObject{
struct _JsonPair *jsonPair;
struct _JsonPair *lastJsonPair;
struct _JsonObject *next;
int length;
} JsonObject;


其中JsonPair即为json键值对,可以存储的值为字符串或者json数组,定义valueType用来区分jsonPair中存储内容的类型。struct _JsonObject *obj是一个jsonObject 的数组。同时JsonPair又可以串成一个链表。

我们还定义了JsonObject,里面用来存储jsonPair的链表,两个解构是递归定义的。

下图为基本结构



内存管理

单片机上对内存的操作比较麻烦,我们可以直接使用数组作为内存。这样做的好处是内存地址是连续的,我们知道结构体中的地址也是连续的,也就是说我们可以直接把结构体的首地址指向一片足够大的内存,这样结构体变可存值了。定义结构体时应当注意内存对齐。此处我们优化了内存管理结构,将“存储结构的内存”和“存储数据的内存”分离开来,根据情况分别为其分配空间。

char memStructure[MEM_SIZE_STRUCTURE];
char memJsonData[MEM_SIZE_JSONDATA];
char memJsonParse[MEM_SIZE_JSONPARSEDATA];
/******************************************
*Structure Memory Manager
*******************************************/
char *structureBasePtr = memStructure;
char *structureCurrPtr = memStructure;
int structureMemCnt = 0;

//malloc jsonPair
JsonPair *jsonPairMalloc(){
void *ptr = structureCurrPtr;
int size = sizeof(JsonPair);
structureMemCnt += size;
if(structureMemCnt > MEM_SIZE_STRUCTURE)
return NULL;
structureCurrPtr = structureCurrPtr + structureMemCnt;

return (JsonPair *)ptr;
}

//malloc jsonObj
JsonObject *jsonObjectMalloc(){
void *ptr = structureCurrPtr;
int size = sizeof(JsonObject);
structureMemCnt += size;
if(structureMemCnt > MEM_SIZE_STRUCTURE)
return NULL;
structureCurrPtr = structureCurrPtr + structureMemCnt;
return (JsonObject *)ptr;
}

char *structureMemFree(){
memset(memJsonData, 0, MEM_SIZE_STRUCTURE);
structureBasePtr = memJsonData;
structureCurrPtr = memJsonData;
structureMemCnt = 0;
return structureBasePtr;
}

/******************************************
*Data Memory Manager
*******************************************/
char *dataBasePtr = memJsonData;
char *dataCurrPtr = memJsonData;
int dataMemIndex = 0;

//malloc json data memory
char *dataMemMalloc(int size){
char *ptr = dataCurrPtr;
dataCurrPtr = dataCurrPtr + size;
return ptr;
}

//free json data memory
char *dataMemFree(){
memset(dataBasePtr, 0, MEM_SIZE_JSONDATA);
dataBasePtr = dataBasePtr;
dataCurrPtr = dataBasePtr;
dataMemIndex = 0;
return dataBasePtr;
}
/******************************************
*Data Memory Manager
*******************************************/
char *memJsonParseFree(){
memset(dataBasePtr, 0, MEM_SIZE_JSONDATA);
}


目前还不能支持多任务操作系统进行任务间切换,除非为不同任务定义不同的存储空间,否则只能顺序转换。

json生成与解析

有了上面的示意图我们即可知道,json生成其实相当于创建一棵树,然后将其顺序转换为字符串。json的解析就是将字符串按照一定顺序取出,然后创建一棵树。

生成json

/****************************************
*  generate json
*****************************************/
JsonObject *createJsonObject(){

JsonObject *ptr = jsonObjectMalloc();
//json-pair header
ptr->jsonPair = NULL;
//json-pair rear
ptr->lastJsonPair = NULL;
ptr->length = 0;
return ptr;
}

//add a normal key-value pair
JsonObject *addJsonPair(JsonObject *rootObject, char *key, char *value){

JsonPair *jsonPair = jsonPairMalloc();
jsonPair->key = key;
jsonPair->keyLength = strlen(key);
jsonPair->value = value;
jsonPair->valueLength = strlen(value);
jsonPair->valueType = VALUE_TYPE_NORMALPAIR;

if(rootObject->jsonPair == NULL){
rootObject->jsonPair = jsonPair;
rootObject->lastJsonPair = jsonPair;
//jsonPair->prev = NULL;
jsonPair->next = NULL;
}else{
//jsonPair->prev = rootObject->lastJsonPair;
jsonPair->next = NULL;
rootObject->lastJsonPair->next = jsonPair;
rootObject->lastJsonPair = jsonPair;
}

rootObject->length++;

return rootObject;
}

//get json key-value as string
char *generateJsonPairString(char *mem, int *index, JsonPair *jsonPair){
char *str = NULL;

mem[(*index)++] = '"';
memcpy(mem+(*index), jsonPair->key, jsonPair->keyLength);
*index = *index + jsonPair->keyLength;
mem[(*index)++] = '"';

mem[(*index)++] = ':';

memcpy(mem+(*index), jsonPair->value, jsonPair->valueLength);
*index = *index + jsonPair->valueLength;

mem[(*index)] = '\0';
str = mem;
return str;
}

//add a json object array's address
JsonObject *addJsonObjects(JsonObject *rootObject, char *key, JsonObject **childObject){

JsonPair *jsonPair = jsonPairMalloc();
jsonPair->key = key;
jsonPair->keyLength = strlen(key);
jsonPair->obj = childObject;
//(*jsonPair->obj)->length = arrayLength;
jsonPair->valueType = VALUE_TYPE_JSONARRAY;

if(rootObject->jsonPair == NULL){

rootObject->jsonPair = jsonPair;
rootObject->lastJsonPair = jsonPair;
//jsonPair->prev = NULL;
jsonPair->next = NULL;
}else{
//jsonPair->prev = rootObject->lastJsonPair;
jsonPair->next = NULL;
rootObject->lastJsonPair->next = jsonPair;
rootObject->lastJsonPair = jsonPair;
}

rootObject->length++;

return rootObject;
}

//get json array as string
char *generateJsonArrayString(char *mem, int *index, JsonPair *jsonPair){   //JsonObject *jsonObject

char *str = NULL;
int i = 0, j = 0;
int length = 0;

mem[(*index)++] = '"';
memcpy(mem+(*index), jsonPair->key, jsonPair->keyLength);
*index = *index + jsonPair->keyLength;
mem[(*index)++] = '"';
mem[(*index)++] = ':';
mem[(*index)++] = '[';

JsonPair *jsonPairHead;
JsonObject **jsonObject = jsonPair->obj;
JsonObject *jsonObjectCurr;

jsonObjectCurr = jsonObject[0];
for(j=0; j<jsonPair->jsonObjLength; j++){

jsonPairHead = jsonObjectCurr->jsonPair;

mem[(*index)++] = '{';
while(jsonPairHead != NULL){

//JsonPair *innerJsonPair = (*jsonPairHead->obj)->jsonPair;

if(jsonPairHead->valueType == VALUE_TYPE_NORMALPAIR){
//handle normal json pair
generateJsonPairString(mem, index, jsonPairHead);
}else if(jsonPairHead->valueType == VALUE_TYPE_JSONARRAY){
//handle json array pair
generateJsonArrayString(mem, index, jsonPairHead);
}
jsonPairHead = jsonPairHead->next;

mem[(*index)++] = ',';
}
mem[(*index)-1] = '}';
mem[(*index)++] = ',';

jsonObjectCurr = jsonObjectCurr->next;
}
mem[(*index)-1] = ']';
mem[(*index)] = '\0';

str = mem;
return str;
}

//json generate function
char *generateJsonObjectString(char *mem, int *index, JsonObject *jsonObject){

char *str = NULL;
int i;
int length = jsonObject->length;
JsonPair *jsonPairPtr = jsonObject->jsonPair;

mem[(*index)++] = '{';
for(i=0; i<length; i++){
if(jsonPairPtr->valueType == VALUE_TYPE_NORMALPAIR){
generateJsonPairString(mem, index, jsonPairPtr);
}else if(jsonPairPtr->valueType == VALUE_TYPE_JSONOBJ){

}else if(jsonPairPtr->valueType == VALUE_TYPE_JSONARRAY){
generateJsonArrayString(mem, index, jsonPairPtr);
}
jsonPairPtr = jsonPairPtr->next;
mem[(*index)++] = ',';
}
mem[(*index)-1] = '}';
mem[(*index)] = '\0';

return mem;
}


解析json

JsonObject *parseJsonObject(JsonObject *rootJsonObject, char *mem, char* jsonObjectStr, int *index){

int innerIndex = 0;
int keyValueIndex = 0;
int keyLength = 0;
int valueLength = 0;
int i = 0;
int startKeyValueFlag = 0;
int mesureKeyLengthFlag = 0;

char *keyStr = NULL;
char *valueStr = NULL;

int type = -1;

int arrayLength = 0;

rootJsonObject->jsonPair = NULL;
rootJsonObject->lastJsonPair = NULL;
rootJsonObject->length = 0;
rootJsonObject->next = NULL;

while(jsonObjectStr[i] != '\0'){

if(jsonObjectStr[i] == '"' && startKeyValueFlag == 0){
startKeyValueFlag = 1;
}

if(startKeyValueFlag){  //start to parse key-value pair

mesureKeyLengthFlag = 1;
keyValueIndex = 0;
keyLength = 0;
valueLength = 0;
while(jsonObjectStr[i+keyValueIndex] != ',' && jsonObjectStr[i+keyValueIndex] != '}'){

if(jsonObjectStr[i+keyValueIndex] == '"'){  //measure length of key
keyValueIndex++;
}

if(jsonObjectStr[i+keyValueIndex] == ':'){  //measure length of value
mesureKeyLengthFlag = 0;
}

if(mesureKeyLengthFlag){
keyLength++;
}else{
valueLength++;
}
keyValueIndex++;
}
valueLength = valueLength - 1; //skip ','

innerIndex = i;

//fetch key string
keyLength = keyLength;
keyStr = copyString(mem+(*index), &jsonObjectStr[i+1], keyLength);
*index += (keyLength+2);

//fetch value string
valueStr = copyString(mem+(*index), &jsonObjectStr[i+keyLength+3],valueLength);
*index += (valueLength+1);       //avoid other string rewrite the value's last '\0'

type = getStringType(valueStr);

//create a jsonPair and add this jsonPair to the rootJsonObject
JsonPair *jsonPair = jsonPairMalloc();
jsonPair->key = keyStr;
jsonPair->keyLength = strlen(keyStr);
jsonPair->next = NULL;
if(type == VALUE_TYPE_NORMALPAIR){
jsonPair->value = valueStr;
}else if(type == VALUE_TYPE_JSONOBJ){

}else if(type == VALUE_TYPE_JSONARRAY){
//TODO
//JsonObject *jsonObject =
}
jsonPair->valueType = type;

if(rootJsonObject->jsonPair == NULL){
rootJsonObject->jsonPair = jsonPair;
rootJsonObject->lastJsonPair = rootJsonObject->jsonPair;
}else{
rootJsonObject->lastJsonPair->next = jsonPair;
rootJsonObject->lastJsonPair = rootJsonObject->lastJsonPair->next;
}

i += keyValueIndex;
startKeyValueFlag = 0;
}else{
i++;
}
}

return mem;
}


测试

生成json

char* testNewJsonGenerateUtil(){

dataMemIndex = 0;

JsonObject *rootJsonObject = createJsonObject();

//add key-value pair
addJsonPair(rootJsonObject, "key1", "value1");
addJsonPair(rootJsonObject, "key2", "value2");
addJsonPair(rootJsonObject, "key3", "value3");

//add json array
JsonObject *jsonObject0 = createJsonObject();
addJsonPair(jsonObject0, "key40", "value40");
addJsonPair(jsonObject0, "key50", "value50");

JsonObject *jsonObject1 = createJsonObject();
addJsonPair(jsonObject1, "key41", "value41");
addJsonPair(jsonObject1, "key51", "value51");
jsonObject0->next = jsonObject1;

addJsonObjects(rootJsonObject, "key_arr1", &jsonObject0);
rootJsonObject->lastJsonPair->jsonObjLength = 2;

//generate json string
char *str = generateJsonObjectString(dataBasePtr, &dataMemIndex, rootJsonObject);

//clear memory
//structureMemFree();
//dataMemFree();
printf("json string: \n");
printf(str);

return str;
}


解析生成的json(目前不能解析数组)

void testNewJsonParseUtil(char *jsonStr){

JsonObject *rootJsonObject = createJsonObject();

int index = 0;
char *str = parseJsonObject(rootJsonObject, memJsonParse, jsonStr, &index);

printf("\n\njson data:\n");
printf(rootJsonObject->jsonPair->key);
printf("\n");
printf(rootJsonObject->jsonPair->value);

printf("\n");
printf(rootJsonObject->jsonPair->next->key);
printf("\n");
printf(rootJsonObject->jsonPair->next->value);

printf("\n");
printf(rootJsonObject->jsonPair->next->next->key);
printf("\n");
printf(rootJsonObject->jsonPair->next->next->value);

printf("\n\n");

//clear memory
//structureMemFree();
//memJsonParseFree();
//dataMemFree();
}




目前还没有处理换行等一些问题,有时间了继续完善。

代码托管地址:

https://git.oschina.net/vonchenchen/Embed_C_JSON_Utils.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: