微控制器JSON生成框架
出處 http://my.csdn.net/lidec https://blog.csdn.net/lidec/article/details/50480085
背景
最近買了51822的藍芽開發板,閒暇之餘進行了一些除錯,目前還沒有深究藍芽協議的原理。藉助git上51822的現有安卓例程以及開發板自帶程式,基本可以實現Android手機和開發板間的資料傳遞,那麼,問題來了。
資料用什麼樣的格式傳遞呢?如果資料量小的話可以自定義一些規則進行解析,記得做畢業設計的時候就是自定義了幾個tag,微控制器通過串列埠傳送帶Tag的字串,上位機根據Tag解析資料,顯然這種方法並不通用。Json大概是安卓開發中傳遞資料使用的最廣泛的傳輸格式了,那麼,能不能自己寫個json工具框架呢?當然能了.....只是有點麻煩而已。目前已經完成了微控制器JSON的生成。
實現
微控制器實現一個Json框架有什麼困難呢?我覺得最大的障礙就是記憶體管理了,要知道,這種沒有mmu和linux作業系統的微控制器,很多時候並不能直接進行malloc相關的堆操作。而json這種結構化資料的操作則需要大量輔助的資料結構,比如樹和連結串列都需要我們對記憶體進行頻繁操作,如果不進行特殊處理是很難在微控制器上完成的。
在微控制器上使用記憶體,我們多用的是陣列,在程式碼編譯的時候編譯器回自動給我們的陣列分配一段連續記憶體空間供我們操作。顯然,我們可以利用這段記憶體來當作我們存放結構化資料的記憶體空間,而我們要做的就是提供一套規則,對這段記憶體進行操作。
在實際操作中,由於微控制器的種類繁多,各種函式的實際使用效果也不相同,尤其是sizeof函式,很多時候不能正確測量型別長度,所以對於結構體資料最好是手動指定記憶體大小。
51822中的核心是使用CM0作為微控制器,我們在mdk下使用c語言進行開發。
基本結構
#define JSONTYPE_KV 1
#define JSONTYPE_ARR 2
/**
*鍵值對
*/
typedef struct _JSONNode{
struct _JSONNode *next;
struct _JSONNode *prev;
//JSONOBJ
int type; //Node型別,分為普通鍵值對和JSON陣列
char *key; //鍵
int keyLength; //鍵字串的長度
//key_value type==JSONTYPE_KV
char *value; //值
int valueLength; //值字串長度
//JSONARRAY ARRAY type==JSONTYPE_ARR
int arrayLength; //值為JSON陣列時陣列元素個數<span style="font-family: Arial, Helvetica, sans-serif;"> </span>
struct _JSONObjectNode **objectNode; //陣列
}JSONNode;
/**
* JSONObject 主要用於JSON陣列
*/
typedef struct _JSONObjectNode{
//JSONARRAY
JSONNode **jsonNode; //JSON Obj中的jsonNode連結串列,也就是每個JSON物件中的所有鍵值對都有連結串列儲存
int length; //連結串列的長度
struct _JSONObjectNode *next; //指向下一個jsonNode節點
}JSONObjectNode;
/**
* JSON主幹列表
*/
typedef struct _JSONList{
JSONNode *start;
JSONNode *end;
int length;
}JSONList;
具體實現方法
記憶體管理
<span style="font-weight: normal;"><span style="font-size:12px;">char TypeMem[MY_TYPE_MALLOC_SIZE];
char *mPtr = TypeMem;
char *mPtrRecord = TypeMem;
//**********自定義的malloc***********
void *myMemMalloc(int size){
char *ptr = mPtr;
mPtr = mPtr + size;
return ptr;
}
void myMemFree(void *ptr){
//myfree(ptr);
mPtr = mPtrRecord;
memset(mPtrRecord, 0, MY_TYPE_MALLOC_SIZE);
}
void myMemCpy(void *des,void *src,int n){
//mem_memcpy(des, src, n);
memcpy(des, src, n);
}
//**********獲取一個JSONNode的記憶體空間******************
JSONNode *newJSONNode(){
JSONNode *node = myMemMalloc(sizeof(JSONNode));
return node;
}
//***********獲取一個JSONObject的記憶體空間******************
JSONObjectNode *newJSONObjectNode(){
JSONObjectNode *node = myMemMalloc(24);
return node;
}</span></span>
JSON生成
JSONList *initLinkList(){
//int length = sizeof(JSONList); //由於不能保證這個函式在任何微控制器上直接可以使用,此處寫死
JSONList *ret = myMemMalloc(24);
ret->start = NULL;
ret->end = NULL;
ret->length = 0;
return ret;
}
void initJSONNode(JSONNode *node, char *key, char *value, int type){
node->key = key;
node->value = value;
node->keyLength = strlen(key);
node->valueLength = strlen(value);
node->type = type;
}
/**
* 新增一個普通JSON鍵值對
*/
void addNode(JSONList *list, char *key, char *value){
JSONNode *node = NULL;
node = newJSONNode();
if(list->length == 0){
node->next = NULL;
node->prev = NULL;
list->start = node;
list->end = node;
}else{
node->next = NULL;
node->prev = list->end;
list->end->next = node;
list->end = node;
}
list->length++;
node->type = JSONTYPE_KV;
node->keyLength = strlen(key);
node->valueLength = strlen(value);
node->key = key;
node->value = value;
}
/**
* 新增一個JSON Array鍵值對
*/
void addJSONArray(JSONList *list, char *key, JSONObjectNode **value, int length){
JSONNode *node = NULL;
int i;
JSONNode *indexNode = list->start;
int sameKeyFlag = 0;
while(indexNode != NULL){ //遍歷檢視是否已經有這個鍵
int cmp = strcmp(indexNode->key, key);
if(cmp == 0){
sameKeyFlag = 1;
node = indexNode; //如果存在,直接獲取節點
break;
}
indexNode = indexNode->next;
}
if(sameKeyFlag == 0){ //如果不存在,建立一個節點加入連結串列
node = newJSONNode();
node->arrayLength = -1;
if(list->length == 0){
node->next = NULL;
node->prev = NULL;
list->start = node;
list->end = node;
}else{
node->next = NULL;
node->prev = list->end;
list->end->next = node;
list->end = node;
}
list->length++;
}
node->type = JSONTYPE_ARR;
node->keyLength = strlen(key);
//node->valueLength = strlen(value);
node->key = key;
//node->array[node->arrayIndex] = value;
//node->arrayIndex++;
node->value = NULL;
node->valueLength = 0;
node->objectNode = value;
node->arrayLength = length;
}
/**
* 將普通jsonNode轉換為字串的形式
*/
char *getJSONObjString(char *mem, int *index, JSONNode *nodePtr){
char *str = NULL;
mem[(*index)++] = '"';
memcpy(mem+(*index), nodePtr->key, nodePtr->keyLength);
*index = *index + nodePtr->keyLength;
mem[(*index)++] = '"';
mem[(*index)++] = ':';
memcpy(mem+(*index), nodePtr->value, nodePtr->valueLength);
*index = *index + nodePtr->valueLength;
mem[(*index)] = '\0';
str = mem;
return str;
}
/**
* 將json陣列轉換為字串,如果嵌套了陣列則會遞迴轉換
*/
char *getJSONArrayString(char *mem, int *index, JSONNode *nodePtr){
char *str = NULL;
int i,j;
int length = nodePtr->arrayLength;
int type;
mem[(*index)++] = '"';
memcpy(mem+(*index), nodePtr->key, nodePtr->keyLength);
*index = *index + nodePtr->keyLength;
mem[(*index)++] = '"';
mem[(*index)++] = ':';
if(length > 0){
mem[(*index)++] = '[';
for(i=0; i<length; i++){
JSONObjectNode *objectNode;
if(i == 0){
objectNode = nodePtr->objectNode[i];
}else{
objectNode = objectNode->next;
}
mem[(*index)++] = '{';
for(j=0; j<objectNode->length; j++){
type = objectNode->jsonNode[j]->type;
if(type == JSONTYPE_KV){
getJSONObjString((mem), index, objectNode->jsonNode[j]);
}else if(type == JSONTYPE_ARR){
getJSONArrayString((mem), index, objectNode->jsonNode[j]);
}
mem[(*index)++] = ',';
}
mem[(*index)-1] = '}';
if(i < nodePtr->arrayLength-1){
mem[(*index)++] = ',';
}
}
mem[(*index)++] = ']';
}
mem[(*index)] = '\0';
str = mem;
return str;
}
/**
* 轉換主幹JSON列表為字串
*/
char *getJsonString(JSONNode **start, int length){
int i,j;
int arrayLength;
JSONNode *nodePtr = *start;
char *jsonStr = myMemMalloc(256);
int index = 0;
jsonStr[0] = '{';
index++;
for(i=0; i<length; i++){
if(nodePtr != NULL){
if(nodePtr->type == JSONTYPE_KV){
getJSONObjString(jsonStr, &index, nodePtr);
}else if(nodePtr->type == JSONTYPE_ARR){
getJSONArrayString(jsonStr, &index, nodePtr);
}
jsonStr[index] = ',';
index++;
}
nodePtr = nodePtr->next;
}
jsonStr[index-1] = '}';
jsonStr[index] = '\0';
return jsonStr;
}
使用例程
char* testJSON(){
JSONList *list = initLinkList(); //初始化主幹list
JSONObjectNode *obj1 = newJSONObjectNode(); //初始化jsonArray中的元素
JSONObjectNode *obj2 = newJSONObjectNode();
obj1->jsonNode = myMemMalloc(24);
obj2->jsonNode = myMemMalloc(24);
addNode(list, "name", "chen"); //新增鍵值對
addNode(list, "abcd", "chenchen");
addNode(list, "gender", "female");
addNode(list, "age", "27");
JSONNode *node1 = newJSONNode(); //給jsonArray中的元素賦值
initJSONNode(node1, "key1", "value1", JSONTYPE_KV);
JSONNode *node2 = newJSONNode();
initJSONNode(node2, "key2", "value2", JSONTYPE_KV);
obj1->jsonNode[0] = node1; //將jsonArray中的元素連結
obj1->jsonNode[1] = node2;
obj1->length = 2;
JSONNode *node3 = newJSONNode();
initJSONNode(node3, "key3", "value3", JSONTYPE_KV);
JSONNode *node4 = newJSONNode();
initJSONNode(node4, "key4", "value4", JSONTYPE_KV);
obj2->jsonNode[0] = node3;
obj2->jsonNode[1] = node4;
obj2->length = 2;
obj1->next = obj2; //將jsonArray中的資料串起來
addJSONArray(list, "array", &obj1, 2); //為jsonArray加一個鍵
char *str = getJsonString(&(list->start), list->length); //生成json字串
return str;
}
由於開發板串列埠驅動不對,我們無法直接看到列印資料,我們直接將資料通過藍芽返回了手機
這就是我們最後生成的json資料。
最後付一下原始碼下載的地址,有待繼續完善https://git.oschina.net/vonchenchen/Embed_C_JSON_Utils.git
---------------------
作者:vonchenchen1
來源:CSDN
原文:https://blog.csdn.net/lidec/article/details/50480085
版權宣告:本文為博主原創文章,轉載請附上博文連結!