部門的產品使用自己公司研發的系統,嵌入式web服務器移植的是goahead2.5的,服務器和前端使用JSON交互,移植的cJSON庫,所以這段時間對JSON的使用做個簡單的筆記,cJSON.h提供出來的接口很多,但是感覺平時使用的也就那么幾個。
在做測試的時候,通過創建json對象,添加節點,然后保存,讀取,輸出這樣的一個流程,發現當添加節點數多的時候,會會出現長時間的等待,當時好像是一萬行的數據量,整個創建過程花費了2,3秒鍾,所以當更多數據量的時候,花費的時間可能更長。最后發現是這個函數導致的結果,源碼如下,可以看到它每添加一個item,都是從頭往后找,等找到最后一個節點的時候,然后把item賦值給最后一個節點的next,所以節點越多,時間也就更長了。
void cJSON_AddItemToArray(cJSON *array, cJSON *item)
void cJSON_AddItemToArray(cJSON *array, cJSON *item)
{ cJSON *c=array->child; if (!item) return; if (!c) { array->child=item; } else { while (c && c->next) c=c->next; suffix_object(c,item); } }
查看cJSON的結構體,會發現,json結構有next和pre兩個指針,也就是它的鏈表是個雙向鏈表,但是就奇怪為何找節點卻不用這個優點,非得單向去找。
typedef struct cJSON { struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ int type; /* The type of the item, as above. */ char *valuestring; /* The item's string, if type==cJSON_String */ int valueint; /* The item's number, if type==cJSON_Number */ double valuedouble; /* The item's number, if type==cJSON_Number */ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ } cJSON;
所以解決的思路就在這了,有兩種方式解決:
1,利用array的pre指針,每次插入item后,同時將其指針保存在array->child->pre中,這樣我每次插入節點,都只需要找到第一個節點的pre指針,然后將item插到該地址之后,即可。
cJSON * c = array->child; if(!item) { return ; } if(!c) { array->child = item; array->child->prev = item; } else { array->child->prev->next = item; array->child->prev = item; item->next = NULL;
}
2,第二種方式就很簡單,通過修改json結構體實現目的,在結構體中添加一個成員 struct cJSON * last;每次添加item的時候,同時將它的指針賦值給array->child->last;
這樣每次添加的時候,只需要查找last指針就可以找到最后一個節點。
cJSON * c = array->child; if(!item) { return ; } if(!c) { array->child = item; array->child->last = item; } else { array->child->last->next = item; array->child->last = item; item = NULL; }
用的最多的object對象就是這些了。
#define cJSON_AddNullToObject(object,name)
#define cJSON_AddTrueToObject(object,name)
#define cJSON_AddFalseToObject(object,name)
#define cJSON_AddBoolToObject(object,name,b)
#define cJSON_AddNumberToObject(object,name,n)
#define cJSON_AddStringToObject(object,name,s)
還有數組對象
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
如果是將一個數組添加進對象就可以用
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
當用完json對象時候,就必須記者刪除
cJSON_Delete(cJSON*);
將一個字符串解析成json對象
extern cJSON *cJSON_Parse(const char *value);
將一個json對象轉換成char *,但是這個字符串必須是手動刪除
extern char *cJSON_Print(cJSON *item);