網上看到的一片關於json-c的文章。收藏一下,忘記了出處,盡請作者諒解。
JSON c語言開發指南
1. 引言
本文檔是基於json-c 庫對數據交換進行開發所編寫的開發指南,及詳細解釋json-c庫中常用api。 適用於開發人員使用c語言對json的編程。
(注: 此文檔json-c庫版本為0.8——json-c-0.8)
2. 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的數值非常相似。除去未曾使用的八進制與十六進制格式。除去一些編碼細節。
3. JSON 庫函數說明
3.1 JSON對象的生成
Json對象的類型:
json_type_object, “名稱/值”對的集合
Json對象的值類型
json_type_boolean,
json_type_double,
json_type_int,
json_type_array, “值”的集合
json_type_string
struct json_object * json_object_new_object();
說明:
創建個空的json_type_object類型JSON對象。
struct json_object* json_object_new_boolean(Boolean b);
說明:
創建個json_type_boolean值類型json對象
Boolean json_object_get_boolean(struct json_object *obj);
說明:
從json對象中boolean值類型得到boolean值
同樣:
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)
struct json_object * json_object_new_array();
說明:
創建個空的json_type_array類型JSON數組值對象。
struct json_object * json_tokener_parse(char *str);
說明:
由str里的JSON字符串生成JSON對象,str是json_object_to_json_string() 生成的。
參數:
str – json字符串
struct json_object * json_object_object_get(struct json_object * json,char *name);
說明:
從json中按名字取一個對象。
參數:
json – json對象
name - json域名字
3.2 JSON對象的釋放
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對象
樣例片段:
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對象的操作
Int json_object_is_type(struct json_object * this, enum json_type type)
說明:
檢查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
enum json_type json_object_get_type(struct json_object * this )
說明:
得到json_object的類型。
參數:
this – json對象
char * json_object_to_json_string(struct json_object * this)
說明:
將json_object內容轉換json格式字符串,其中可能含有轉義符。
參數:
this – json對象
返回值:
Json格式字符串
void json_object_object_add(struct json_object* obj, char *key, struct json_object *val);
說明:
添加個對象域到json對象中
參數:
Obj – json對象
key – 域名字
val – json值對象
void json_object_object_del(struct json_object* obj, char *key);
說明:
刪除key值json對象
參數:
ob j – json對象
key – 域名字
int json_object_array_length(struct json_object *obj);
說明:
得到json對象數組的長度。
參數:
ob j – json數組值對象
extern int json_object_array_add(struct json_object *obj,
struct json_object *val);
說明:
添加一元素在json對象數組末端
參數:
ob j – json數組值對象
val – json值對象
*
int json_object_array_put_idx(struct json_object *obj, int idx,
struct json_object *val);
說明:
在指定的json對象數組下標插入或替換一個json對象元素。
參數:
ob j – json數組值對象
val – json值對象
idx – 數組下標
struct json_object * json_object_array_get_idx(struct json_object * json_array,int i);
說明:
從數組中,按下標取JSON值對象。
參數:
json_array – json 數組類型對象
i – 數組下標位置
定義宏 json_object_object_foreach(obj,key,val)
說明:
遍歷json對象的key和值 (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);
4. JSON實例開發
4.1 樣例1
#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);
new_obj = json_tokener_parse("12.3");
/*得到json double類型
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 } }
備注
Json-c-0.8版本對0.7版本做的更新:
* 添加va_end 給指針至NULL 增加程序健壯性
* 添加宏使得能夠編譯出調試代碼
* 解決個bug 在指數中使用大寫字母E
* 添加 stddef.h 頭文件
* 允許編譯json-c 使用-Werror