单片机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; }
测试
生成jsonchar* 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
相关文章推荐
- JavaScript_Json使用
- Javascript 使用Ajax
- #学习笔记#(28)JS瀑布流-慕课
- Jsp实现筛选并压缩文件批量下载
- input文本框只能输入数字
- JavaScript优化(三)
- xml json 互转
- JavaScript设计模式学习笔记
- javascript日期字符串和日期对象相互转换
- 使用js中断表单的提交动作的方法
- 跟我一起学extjs5(18--模块的新增、改动、删除操作)
- Javascript 如何修改CSS样式(网页样式) 补充说明
- jsp乱码
- JSP动作指令初级解析
- EXTJS Ajax请求中文乱码
- javascript indexOf startWith
- JSON例子应用
- 图表插件 - chart.js (柱状图) 学习总结
- struts2如何在提交前进行js代码判断
- 【JSOI2015】字符串树