1. 程式人生 > 實用技巧 >JSON-C語言開發指南

JSON-C語言開發指南

一、前言

本文件是基於json-c庫對資料交換進行開發所編寫的開發指南,及詳細解釋json-c庫中常用api。 適用於開發人員使用c語言對json的程式設計
(注:此文件json-c庫版本為0.8——json-c-0.8)

二、JSON簡介
JSON(JavaScript Object Notation) 是一種輕量級的資料交換格式。易於人閱讀和編寫。
同時也易於機器解析和生成。它基於JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一個子集。JSON採用完全獨立於語言的文字格式,但是也使用了類似於C語言家族的習慣(包括C, C++, C#, Java, JavaScript, Perl, Python等)。這些特性使JSON成為理想的資料交換語言。

跟XML相比,JSON的優勢在於格式簡潔短小,特別是在處理大量複雜資料的時候,這個優勢便顯得非常突出。從各瀏覽器的支援來看,JSON解決了因不同瀏覽器對XML DOM解析方式不同而引起的問題。

2.1 JSON兩種結構
“名稱/值”對的集合(A collection of name/value pairs):

----不同的語言中,它被理解為物件(object),紀錄(record),結構(struct),字典(dictionary),

----雜湊表(hash table),有鍵列表(keyed list),或者關聯陣列 (associative array)。

值的有序列表(An ordered list of values):

----在大部分語言中,它被理解為陣列(array)。

這些都是常見的資料結構。事實上大部分現代計算機語言都以某種形式支援它們。這使得一種資料格式在同樣基於這些結構的程式語言之間交換成為可能。

2.2 JSON具有以下這些形式:
物件是一個無序的“‘名稱/值’對”集合;
一個物件以“{”(左括號)開始,“}”(右括號)結束;
每個“名稱”後跟一個“:”(冒號);
“‘名稱/值’ 對”之間使用“,”(逗號)分隔。

陣列是值(value)的有序集合。
一個數組以“[”(左中括號)開始,“]”(右中括號)結束;
值之間使用“,”(逗號)分隔。

值(value)可以是雙引號括起來的字串(string)、數值(number)、true、false、 null、物件(object)或者陣列(array)。


這些結構可以巢狀。

字串(string)是由雙引號包圍的任意數量Unicode字元的集合,使用反斜線轉義。
一個字元(character)即一個單獨的字串(character string)。
字串(string)與C或者Java的字串非常相似。

數值(number)也與C或者Java的數值非常相似。
除去未曾使用的八進位制與十六進位制格式。除去一些編碼細節。

三、JSON庫函式說明
3.1 JSON物件的生成

Json物件的型別:
json_type_object, “名稱/值”對的集合

/* Json物件的值型別 */
json_type_boolean,
json_type_double,
json_type_int,
json_type_array, “值”的集合
json_type_string

/* 建立個空的json_type_object型別JSON物件 */
struct json_object * json_object_new_object();

/* 建立個json_type_boolean值型別json物件 */
struct json_object* json_object_new_boolean(boolean b);

/* 從json物件中boolean值型別得到boolean值 */
boolean json_object_get_boolean(struct json_object *obj);

同樣:
struct json_object* json_object_new_int(int i)
int json_object_get_int(struct json_object *this)
struct json_object* json_object_new_double(double d)
double json_object_get_double(struct json_object *this)
struct json_object* json_object_new_string(char *s)
char* json_object_get_string(struct json_object *this)


/* 建立個空的json_type_array型別JSON陣列值物件。 */
struct json_object * json_object_new_array();

/* 由str裡的JSON字串生成JSON物件,str是son_object_to_json_string() 生成的。
 * 引數:
 * str – json字串
 */
struct json_object * json_tokener_parse(char *str); //

/* 從json中按名字取一個物件。
 * 引數:
 * json – json物件
 * name - json域名字
 */
struct json_object * json_object_object_get(struct json_object * json,char *name);

3.2 JSON物件的釋放

/* 增加物件引用計數。使用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物件
 */
struct json_object * * json_object_get(struct json_object * this)

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


/* 樣例片段:*/
my_string = json_object_new_string("\t"); /*輸出 my_string= */ \t(table鍵)
printf("my_string=%s\n", json_object_get_string(my_string));

/*轉換json格式字串 輸出my_string.to_string()="\t"*/
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));

/*釋放資源*/
json_object_put(my_string);


3.3 JSON物件的操作

/* 檢查json_object是json的某個型別 
 * 引數:
 * this: json_object 例項
 * type: json_type_boolean,json_type_double, json_type_int, json_type_object, json_type_array, json_type_string
 */
int json_object_is_type(struct json_object * this, enum json_type type)

/* 得到json_object的型別。
 * 引數:
 * this – json物件
 */
enum json_type json_object_get_type(struct json_object * this )

/* 將json_object內容轉換json格式字串,其中可能含有轉義符。
 * 引數:
 * this – json物件
 * 返回值:
 * json格式字串
 */
char * json_object_to_json_string(struct json_object * this)

/* 添加個物件域到json物件中
 * 引數:
 * obj – json物件
 * key – 域名字
 * val – json值物件
 */
void json_object_object_add(struct json_object* obj, char *key, struct json_object *val);


/* 刪除key值json物件
 * 引數:
 * obj – json物件
 * key – 域名字
 */
void json_object_object_del(struct json_object* obj, char *key);

/* 得到json物件陣列的長度。
 * 引數:
 * obj – json陣列值物件
 */
int json_object_array_length(struct json_object *obj);

/* 新增一元素在json物件陣列末端
 * 引數:
 * obj – json陣列值物件
 * val – json值物件
 */
extern int json_object_array_add(struct json_object *obj, struct json_object *val);

/* 在指定的json物件陣列下標插入或替換一個json物件元素。
 * 引數:
 * obj – json陣列值物件
 * val – json值物件
 * idx – 陣列下標
 */
int json_object_array_put_idx(struct json_object *obj, int idx, struct json_object *val);


/* 從陣列中,按下標取JSON值物件。
 * 引數:
 * json_array – json 陣列型別物件
 * i – 陣列下標位置
 */
struct json_object * json_object_array_get_idx(struct json_object * json_array,int i);

/* 定義巨集。遍歷json物件的key和值 (key, val預設引數不變)*/
json_object_object_foreach(obj,key,val)

 

============================================
樣例片段:

/*建立個空json物件值陣列型別*/
my_array = json_object_new_array();

/*新增json值型別到陣列中*/
json_object_array_add(my_array, json_object_new_int(1));
json_object_array_add(my_array, json_object_new_int(2));
json_object_array_add(my_array, json_object_new_int(3));
json_object_array_put_idx(my_array, 4, json_object_new_int(5));
printf("my_array=\n");

for(i=0; i < json_object_array_length(my_array); i++) {
struct json_object *obj = json_object_array_get_idx(my_array, i);
printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
}

printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
my_object = json_object_new_object();

/*新增json名稱和值到json物件集合中*/
json_object_object_add(my_object, "abc", json_object_new_int(12));
json_object_object_add(my_object, "foo", json_object_new_string("bar"));
json_object_object_add(my_object, "bool0", json_object_new_boolean(0));
json_object_object_add(my_object, "bool1", json_object_new_boolean(1));
json_object_object_add(my_object, "baz", json_object_new_string("bang"));

/*同樣的key 新增會替換掉*/
json_object_object_add(my_object, "baz", json_object_new_string("fark"));
json_object_object_del(my_object, "baz");

/*新增陣列集合到json物件中*/
json_object_object_add(my_object, "arr", my_array);
printf("my_object=\n");

/*遍歷json物件集合*/
json_object_object_foreach(my_object, key, val) {
printf("\t%s: %s\n", key, json_object_to_json_string(val));
}
json_object_put(my_object);

四、 JSON例項開發
樣例

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include "json.h"

int main(int argc, char **argv)
{
struct json_tokener *tok;
struct json_object *my_string, *my_int, *my_object, *my_array;
struct json_object *new_obj;
int i;

my_string = json_object_new_string("\t");

/*輸出 my_string= */
printf("my_string=%s\n", json_object_get_string(my_string));

/*轉換json格式字串 輸出my_string.to_string()="\t"*/
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string)); 

/*釋放資源*/
json_object_put(my_string);

my_string = json_object_new_string("\\");
printf("my_string=%s\n", json_object_get_string(my_string));
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));
json_object_put(my_string);

my_string = json_object_new_string("foo");
printf("my_string=%s\n", json_object_get_string(my_string));
printf("my_string.to_string()=%s\n", json_object_to_json_string(my_string));

my_int = json_object_new_int(9);
printf("my_int=%d\n", json_object_get_int(my_int));
printf("my_int.to_string()=%s\n", json_object_to_json_string(my_int));

/*建立個空json物件值陣列型別*/
my_array = json_object_new_array();
/*新增json值型別到陣列中*/
json_object_array_add(my_array, json_object_new_int(1));
json_object_array_add(my_array, json_object_new_int(2));
json_object_array_add(my_array, json_object_new_int(3));
json_object_array_put_idx(my_array, 4, json_object_new_int(5));
printf("my_array=\n");
for(i=0; i < json_object_array_length(my_array); i++) {
struct json_object *obj = json_object_array_get_idx(my_array, i);
printf("\t[%d]=%s\n", i, json_object_to_json_string(obj));
}

printf("my_array.to_string()=%s\n", json_object_to_json_string(my_array));
my_object = json_object_new_object();

/*新增json名稱和值到json物件集合中*/
json_object_object_add(my_object, "abc", json_object_new_int(12));
json_object_object_add(my_object, "foo", json_object_new_string("bar"));
json_object_object_add(my_object, "bool0", json_object_new_boolean(0));
json_object_object_add(my_object, "bool1", json_object_new_boolean(1));
json_object_object_add(my_object, "baz", json_object_new_string("bang"));

/*同樣的key 新增會替換掉*/
json_object_object_add(my_object, "baz", json_object_new_string("fark"));
json_object_object_del(my_object, "baz");

printf("my_object=\n");
/*遍歷json物件集合*/
json_object_object_foreach(my_object, key, val) {
printf("\t%s: %s\n", key, json_object_to_json_string(val));
}
printf("my_object.to_string()=%s\n", json_object_to_json_string(my_object));

/*對些不規則的串做了些解析測試*/
new_obj = json_tokener_parse("\"\003\"");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("/* hello */\"foo\"");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("// hello\n\"foo\"");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("\"\\u0041\\u0042\\u0043\"");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("null");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("True");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("12");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

/*得到json double型別
new_obj = json_tokener_parse("12.3");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("[\"\\n\"]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);


new_obj = json_tokener_parse("[\"\\nabc\\n\"]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("[null]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("[]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("[false]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("[\"abc\",null,\"def\",12]");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{}");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{ \"foo\": \"bar\" }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{ \"foo\": \"bar\", \"baz\": null, \"bool0\": true }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{ \"foo\": [null, \"foo\"] }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{ \"abc\": 12, \"foo\": \"bar\", \"bool0\": false, \"bool1\": true, \"arr\": [ 1, 2, 3, null, 5 ] }");
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj);

new_obj = json_tokener_parse("{ foo }");
if(is_error(new_obj)) printf("got error as expected\n");
new_obj = json_tokener_parse("foo");

if(is_error(new_obj)) printf("got error as expected\n");
new_obj = json_tokener_parse("{ \"foo");
if(is_error(new_obj)) printf("got error as expected\n");
/* test incremental parsing */
tok = json_tokener_new();
new_obj = json_tokener_parse_ex(tok, "{ \"foo", 6);
if(is_error(new_obj)) printf("got error as expected\n");
new_obj = json_tokener_parse_ex(tok, "\": {\"bar", 8);
if(is_error(new_obj)) printf("got error as expected\n");
new_obj = json_tokener_parse_ex(tok, "\":13}}", 6);
printf("new_obj.to_string()=%s\n", json_object_to_json_string(new_obj));
json_object_put(new_obj); 
json_tokener_free(tok);

json_object_put(my_string);
json_object_put(my_int);
json_object_put(my_object);
json_object_put(my_array);

/*如果前面沒有新增到物件中, 必須顯示釋放,
*如果新增到物件中,已經釋放物件,則無需呼叫, 
*在這務必小心,否則很容易記憶體洩漏*/

return 0;

}

輸出結果:

my_string=
my_string.to_string()="\t"
my_string=\
my_string.to_string()="\\"
my_string=foo
my_string.to_string()="foo"
my_int=9
my_int.to_string()=9
my_array=
[0]=1
[1]=2
[2]=3
[3]=null
[4]=5
my_array.to_string()=[ 1, 2, 3, null, 5 ]
my_object=
abc: 12
foo: "bar"
bool0: false
bool1: true
my_object.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true }
new_obj.to_string()="\u0003"
new_obj.to_string()="foo"
new_obj.to_string()="foo"
new_obj.to_string()="ABC"
new_obj.to_string()=null
new_obj.to_string()=true
new_obj.to_string()=12
new_obj.to_string()=12.300000
new_obj.to_string()=[ "\n" ]
new_obj.to_string()=[ "\nabc\n" ]
new_obj.to_string()=[ null ]
new_obj.to_string()=[ ]
new_obj.to_string()=[ false ]
new_obj.to_string()=[ "abc", null, "def", 12 ]
new_obj.to_string()={ }
new_obj.to_string()={ "foo": "bar" }
new_obj.to_string()={ "foo": "bar", "baz": null, "bool0": true }
new_obj.to_string()={ "foo": [ null, "foo" ] }
new_obj.to_string()={ "abc": 12, "foo": "bar", "bool0": false, "bool1": true, "arr": [ 1, 2, 3, null, 5 ] }
got error as expected
got error as expected
got error as expected
new_obj.to_string()={ "foo": { "bar": 13 } }