[時間:2017-04] [狀態:Open]
[關鍵詞:數據交換格式,json,jsoncpp,c++,json解析,OpenSource]
json簡介
本文僅僅是添加我個人對json格式的理解,更詳細的格式建議參考官網的JSON介紹及標准文檔。
json中僅支持兩種結構:
- name->value鍵值對(pair)的集合,一般稱為對象(object)。
- 值的有序表,一般稱為數組(array)。
1. pair
先從鍵值對(pair)開始,一個pair的通常結構是:
string:value
鍵值之間的對應關系使用:表示,左邊的為name,右邊的為value。
一般key使用字符串,當然也可以使用數字,但是不推薦。
value的取值就比較隨便,可以是任何任何json支持的類型(比如object,array,string,number,true/false,null等)。
2. object
object可以認為是多個pair的集合,官網上給出的示意圖如下:

其語法是以{作為object開始,以}作為object結束,不同的pair之間使用,分割。
需要說明的是object中的數據存儲是無序的。
下面是一個比較典型的object構成
{
"name" : "tocy",
"age" : 1000
}
3. array
array是value的有序集合。先看官網上針對array結構的示意圖:

其語法是以[作為array起始,以]作為array結束,array元素之間使用,分割。
實際使用中建議在array中使用統一的類型,否則解析起來會麻煩點。
比如下面語法是合法的:
[{"name":"tocy"}, {"age":1000}, {"domain":"cn"}]
當然下面這種寫法也是可以的,[1, "ts", true, {"key":45}]
至於其他的string和number支持的格式,建議參考json官方介紹。
JsonCpp的使用
json的官網上有很多關於json解析的工具,可以從中選擇一個你喜歡的。
我主要在c++下使用json,我選擇了JsonCpp,官網是:https://github.com/open-source-parsers/jsoncpp。
下載完源碼之后為了使用方便,直接將源碼嵌入到工程中,進入源碼所在目錄,先生成一個完整的頭文件和cpp文件,命令如下:
python amalgamate.py
然后將dist文件夾拷貝到工程目錄就可以使用了。(包含json/json.h、json/json-forwards.h、json.cpp)
注意:本部分用例代碼可能為了簡化期間,並未做錯誤異常判斷,僅供參考。
示例1 從文件中讀取json文件並解析
首先我們提供一個json文件,這里命名為"checkjson.json",其中數據如下:
{
"name" : "tocy",
"age" : 1000
}
這里面保存的是最簡單的object,我們可以使用下面代碼將其讀入並解析:
void demo_simple()
{
ifstream ifs;
ifs.open("checkjson.json");
assert(ifs.is_open());
Json::Reader reader;
Json::Value root;
if (!reader.parse(ifs, root, false))
{
cerr << "parse failed \n";
return;
}
string name = root["name"].asString(); // 實際字段保存在這里
int age = root["age"].asInt(); // 這是整型,轉化是指定類型
}
這里是簡單的map訪問,然后直接讀取對應字段即可。
示例2 從內存中讀取json數據(object)
我們在內存中定義一段json數據,然后解析,這次我們在json中添加內嵌array的object。代碼如下:
void demo_parse_mem_object()
{
const char json_data[] =
"{\"name\" : \"Tocy\", \"salary\" : 100, \"msg\" : \"work hard\", \
\"files\" : [\"1.ts\", \"2.txt\"]}";
Json::Reader reader;
Json::Value root;
// reader將Json字符串解析到root,root將包含Json里所有子元素
if (!reader.parse(json_data, json_data + sizeof(json_data), root))
{
cerr << "json parse failed\n";
return;
}
cout << "demo read from memory ---------\n";
string name = root["name"].asString();
int salary = root["salary"].asInt();
string msg = root["msg"].asString();
cout << "name: " << name << " salary: " << salary;
cout << " msg: " << msg << endl;
cout << "enter files: \n";
Json::Value files = root["files"]; // read array here
for (unsigned int i = 0; i < files.size(); ++i)
{
cout << files[i].asString() << " ";
}
cout << endl << endl;
}
示例3 從內存中解析json數據(array)
這次我們從提供一個以array封裝的json數據,解析邏輯如下:
void demo_parse_mem_array()
{
const char json_data[] =
"[{\"name\" : \"Tocy\", \"salary\" : 100}, {\"name\" : \"Kit\", \"salary\" : 89}, \
\"a json note\"]";
Json::Reader reader;
Json::Value root;
// reader將Json字符串解析到root,root將包含Json里所有子元素
if (!reader.parse(json_data, json_data + sizeof(json_data), root))
{
cerr << "json parse failed\n";
return;
}
cout << "demo read from memory using array---------\n";
unsigned int count = root.size() - 1;
for (unsigned int i = 0; i < count; ++i)
{
string name = root[i]["name"].asString();
int salary = root[i]["salary"].asInt();
cout << "name: " << name << " salary: " << salary << endl;
}
cout << "last msg: " << root[count].asString() << endl;
cout << endl << endl;
}
示例4 簡單json數據封裝
前面三個是關於json數據解析的例子,下面是關於json數據封裝的例子。
首先我們生成示例1的數據,代碼如下:
void demo_write_simple()
{
Json::Value root;
Json::FastWriter writer;
Json::Value person;
person["name"] = "tocy";
person["age"] = 1000;
root.append(person);
string json_file = writer.write(root);
cout << "demo write json ==============\n";
cout << json_file << endl;
}
示例5 json封裝-內嵌array的object
首先我們生成示例2的數據,代碼如下:
void demo_write_object()
{
Json::Value root;
Json::FastWriter writer;
root["name"] = "tocy";
root["salary"] = 100;
root["msg"] = "work hard";
Json::Value files;
files[0] = "1.ts";
files[1] = "2.txt";
root["files"] = files;
string json_file = writer.write(root);
cout << "demo write json object ==============\n";
cout << json_file << endl;
}
示例6 json封裝-內嵌object的array
首先我們生成示例3的數據,代碼如下:
void demo_write_array()
{
Json::Value root;
Json::FastWriter writer;
{
Json::Value person;
person["name"] = "Tocy";
person["salary"] = 100;
root[0] = person;
}
{
Json::Value person;
person["name"] = "Kit";
person["salary"] = 89;
root[1] = person;
}
root[2] = "a json note";
string json_file = writer.write(root);
cout << "demo write json ==============\n";
cout << json_file << endl;
}
小結
本文簡單整理了json相關格式。同時針對JsonCpp的用法做簡單總結,僅供參考。
本文相關源碼,可以從我的git下載,位於JsonCppTutorial目錄下。
