1. 程式人生 > >json庫函式入門例子,詳解。--C語言

json庫函式入門例子,詳解。--C語言

// 還是得多動手總結啊,不足之處,還望提醒。編譯的時候,記得加上 -ljson 庫

#include<stdio.h>
#include "json/json.h"

void make_a_common_json_string();

int main()
{
	struct json_object *my_obj;
	//json格式的字串,\"string\".(特殊字元加轉義符)
	char *str="{\"abc\": 123, \"wds\": 12.3, \"qwe\": \"ddd\", \"bool0\": false, \"bool1\": true, \"arr\": [12, 3, 0, 5, null]}";
	//將符合json格式的字串構造為一個json物件
	my_obj = json_tokener_parse(str);
	printf("1-tokener parse: %s\n", json_object_to_json_string(my_obj));
	
	// 在物件裡用key值去找,然後刪除它的key:value.
	json_object_object_del(my_obj, "abc");
	printf("2-tokener parse: %s\n", json_object_to_json_string(my_obj));
	
	struct json_object *ret_obj;
	// 在物件裡用key值去找,獲取它的value值
	ret_obj = json_object_object_get(my_obj, "wds");
	printf("obj_get-wds:%s\n", json_object_to_json_string(ret_obj));
	// 在json_object_object_get 引用一次。
	// 將jso物件的引用計數減1,子物件引用計數為0時釋放所佔用記憶體。
	json_object_put(ret_obj);

	// 獲取不同的json資料型別,int.double.string.array.object.
	struct json_object *val = json_object_new_int(18542);
	// 將key:value加入到物件my_obj中.
	json_object_object_add(my_obj, "wds", val);	
	printf("3-object add: %s\n", json_object_to_json_string(my_obj));
	// 看function詳解1
	json_object_put(val);

	printf("get string:%s\n", json_object_get_string(my_obj));
	printf("get lh:%d\n", json_object_get_object(my_obj));
	printf("get int:%d\n", json_object_get_int(my_obj));

	make_a_common_json_string();
	
	// 看function詳解1
	json_object_put(my_obj);
	return 0;
}

// 這個介面,包含了很多資料型別(array, int, string, object)。組成json包,socket傳輸,為上層提供資料,便於展示。
void make_a_common_json_string()
{
	printf("####################################\n");
	int i=0;
	struct json_object *obj_all	 = json_object_new_object();
	struct json_object *obj_info = json_object_new_object();
	struct json_object *obj_work = json_object_new_object();
	struct json_object *obj_life = json_object_new_object();
	struct json_object *arr_month_grade = json_object_new_array();

	for(i=1; i<13; i++){
		struct json_object *obj_int = json_object_new_int(i);
		json_object_array_add(arr_month_grade, obj_int);	
	}

	//const char *str = "{\"職位\": \"programmer\", \"部門\": \"研發\", \"addres\": \"BJ.3\"}";
	//json_object *obj_str = json_tokener_parse(str);
	
	json_object_object_add(obj_work, "position", json_object_new_string("programmer"));
	json_object_object_add(obj_work, "department", json_object_new_string("make code"));
	json_object_object_add(obj_work, "address", json_object_new_string("BJ.3.103"));
	json_object_object_add(obj_work, "mounth_grade", arr_month_grade);
	
	json_object_object_add(obj_info, "Work", obj_work);

	json_object_object_add(obj_life, "Name", json_object_new_string("DS.wen"));
	json_object_object_add(obj_life, "Age", json_object_new_int(24.34));
	json_object_object_add(obj_life, "M-O", json_object_new_string("Male"));

	json_object_object_add(obj_info, "Life", obj_life);
	
	json_object_object_add(obj_all,"W.DS_Info", obj_info);
	printf("all_string:%s\n", json_object_to_json_string(obj_all));

	json_object_put(obj_all);
	return ;
}


/*************************************列印結果********************************************/
1-tokener parse: { "abc": 123, "wds": 12.300000, "qwe": "ddd", "bool0": false, "bool1": true, "arr": [ 12, 3, 0, 5, null ] }
2-tokener parse: { "wds": 12.300000, "qwe": "ddd", "bool0": false, "bool1": true, "arr": [ 12, 3, 0, 5, null ] }
obj_get-wds:12.300000
3-object add: { "wds": 18542, "qwe": "ddd", "bool0": false, "bool1": true, "arr": [ 12, 3, 0, 5, null ] }
get string:{ "wds": 18542, "qwe": "ddd", "bool0": false, "bool1": true, "arr": [ 12, 3, 0, 5, null ] }
get lh:26383664
get int:0
####################################
all_string:{ "W.DS_Info": { "Work": { "position": "programmer", "department": "make code", "address": "BJ.3.103", "mounth_grade": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ] }, "Life": { "Name": "DS.wen", "Age": 24, "M-O": "Male" } } }
/********************************************************************************************************************/


/-----------------------------function--------------------------------------/

1. struct json_object * * json_object_get(struct json_object * this)
說明: 
增加物件引用計數。使用c庫最關心的是記憶體誰來分配, 誰來釋放. jsonc的記憶體管理方式, 是基於引用計數的記憶體樹(鏈), 如果把一個struct json_object 物件a, add到另一個物件b上, 就不用顯式的釋放(json_object_put) a了, 相當於把a掛到了b的物件樹上, 釋放b的時候, 就會釋放a. 當a即add到b上, 又add到物件c上時會導致a被釋放兩次(double free), 這時可以增加a的引用計數(呼叫函式json_object_get(a)), 這時如果先釋放b, 後釋放c, 當釋放b時, 並不會真正的釋放a, 而是減少a的引用計數為1, 然後釋放c時, 才真正釋放a.
引數:
this – json物件

Void json_object_put(struct json_object * this)
說明:
減少物件引用次數一次,當減少到0就釋放(free)資源
引數:
this – json物件

注:如果對json物件顯式呼叫了json_object_get,之後必須成對呼叫json_object_put,否則將導致該json物件所佔用記憶體洩漏。

2. json_object_new_XXX系列函式 struct json_object* json_object_new_object(void);
struct json_object* json_object_new_int(int i);
struct json_object* json_object_new_double(double d);
struct json_object* json_object_new_array(void);
struct json_object* json_object_new_string(const char *s);
struct json_object* json_object_new_string_len(const char *s, int len);
json_object_new_XXX系列函式用來建立XXX型別的json物件,建立的json物件預設引用計數為1,因此在該物件使用完後也需要呼叫一次json_object_put來把引用計數置0,從而釋放記憶體。


3. json_tokener_parse函式 struct json_object* json_tokener_parse(const char *str);
json_tokener_parse將符合json格式的字串構造為一個json物件,構造的json物件預設引用計數為1,同樣需要在使用完後對該物件呼叫一次json_object_put。


4. is_error巨集
is_error(jso)
如果傳入的字串是非法的json格式,錯誤判斷應該使用is_error巨集,而非 if(NULL != jso),CGI中目前有很多這種錯誤用法(雖然好像沒引發什麼問題)


5. json_object_object_XXX函式
void json_object_object_del(struct json_object* jso, const char *key);
從jso物件中刪除鍵值為key的子物件,並釋放該子物件及鍵值所佔的記憶體(注:可能有文件說json_object_object_del只是刪除而不釋放記憶體,但實際上這是錯誤的)。
struct json_object* json_object_object_get(struct json_object* jso, const char *key); 從jso中獲取鍵值為key的子物件。錯誤判斷同樣應該用is_error(jso)巨集。
void json_object_object_add(struct json_object* jso, const char *key, struct json_object *val); 更新鍵值為key的子項的值。整個過程實際上是這樣的:先從jso中刪除並釋放鍵值key及其值的記憶體,然後重新分配記憶體新增鍵值和新的值,所以json_object_object_add是包含json_object_object_del操作的。


6. json_object_get_XXX系列函式 struct lh_table* json_object_get_object(struct json_object *jso);
const char* json_object_get_string(struct json_object *jso);
int json_object_get_int(struct json_object *jso);
double json_object_get_double(struct json_object *jso); 這類函式只是獲取jso物件的實際資料內容,不更新引用計數,也不分配記憶體。


7. json_object_array_XXX系列函式
struct json_object* json_object_array_get_sub_array(struct json_object *jso, int start_idx, int number);
這個函式用來從一個json陣列物件中取陣列序號start_idx開始的、總共number長度的子陣列物件。分頁顯示功能常用到。注:返回的子陣列是有重新分配記憶體的,所以同樣要對返回的json_object*做一次json_object_put操作來釋放記憶體。
int json_object_array_add(struct json_object *jso,struct json_object *val); 向陣列中新增一個值。
int json_object_array_length(struct json_object *jso); 獲取陣列長度。
int json_object_array_put_idx(struct json_object *jso, int idx, struct json_object *val); 更新陣列中序號為idx那一項的值,老的值同樣會先被釋放。
struct json_object* json_object_array_get_idx(struct json_object *jso, int idx); 獲取陣列中序號為idx那一項的json物件,不更新引用計數,也不分配記憶體。
struct json_object* json_object_array_sort(struct json_object *jso, const char *keyname, int sord ); 根據鍵值為keyname的項的值進行升序或降序排序,只是改變陣列成員的順序,不更新引用計數,也不分配記憶體。