一个用C++写的Json解析与处理库
以下转自:http://blog.csdn.net/ggicci/article/details/10600403
什么是Json?这个库能做什么?
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write.
Json 是一种轻量的数据交换格式,和 XML 一样在 Web 开发中非常常用。在 Ajax 的应用中,前台基本上会用到 JSON 作为数据交换格式,因为在 JS 里面可以通过 JSON.parse() 函数对 JSON 格式的字符串进行解析得到 JS 对象,通过这个 JS 对象可以轻松地获取和修改里面的数据。而这个库 ggicci::Json 可以像 JS 一样通过解析获得一个类似的 C++ 对象。通过这个 C++ 对象,你可以像使用 JS 一样对数据进行获取和修改,语法上基本类似。只不过 C++ 是强类型语言,所以当你在试图用不一样的数据类型去获取里面的值的时候会抛异常。至于 C++ 是否需要 JSON 解析器,答案是肯定的,比如某个 CS 架构的程序,服务器端有某些页面采用 web 技术输出 JSON 数据,客户端是 C++ 客户端,它向这些页面发送 HTTP 请求并接收到 JSON 数据,这些数据就需要解析以配合客户端的使用。当然除非客户端只是输出这些字符串或者客户端采用与 C++ 与 JS 混合编程方式,让 JS 去处理这些数据。
项目地址和文档
Github:https://github.com/ggicci/ggicci--json
GGICCI:http://ggicci.me/works/json
文档:http://ggicci.me/works/json/doc
看一个简单例子
#include <iostream>
#include "gci-json.h"
using namespace std;
using namespace ggicci;
int main(int argc, char const *argv[])
{
// Parse a string to get a Json object
Json json = Json::Parse("{ \
\"id\": 18293, \
\"name\": \"Ggicci\", \
\"birthday\": [1991, 11, 10], \
\"man\": true \
}");
cout << "json = " << json << endl;
cout << "-----------------------" << endl;
cout << "id: " << json["id"] << endl;
cout << "name: " << json["name"] << endl;
cout << "birthday-year: " << json["birthday"][0] << endl;
cout << "birthday-month: " << json["birthday"][1] << endl;
cout << "birthday-day: " << json["birthday"][2] << endl;
cout << "man: " << boolalpha << json["man"] << endl;
cout << "-----------------------" << endl;
json["name"] = "Mingjie Tang";
// add property: method 1
json["school"] = "Northwest A&F University";
// add property: method 2
json.AddProperty("traits", Json::Parse("[]").Push("sympathetic").Push("independent"));
cout << "json = " << json << endl;
cout << "-----------------------" << endl;
json["birthday"].Remove(0);
json.Remove("id").Remove("school");
cout << "json = " << json << endl;
return 0;
}
/*
output:
-----------------------
id: 18293
name: "Ggicci"
birthday-year: 1991
birthday-month: 11
birthday-day: 10
man: true
-----------------------
json = { "birthday": [ 1991, 11, 10 ], "id": 18293, "man": true, "name": "Mingjie Tang", "school": "Northwest A&F University", "traits": [ "sympathetic", "independent" ] }
-----------------------
json = { "birthday": [ 11, 10 ], "man": true, "name": "Mingjie Tang", "traits": [ "sympathetic", "independent" ] }
*/
如果你对 JSON 的处理比较熟悉(你可能会使用 JS 处理 JSON 数据),你会发现上面的代码很好理解。
与 JS 的使用比较(语法层面上)
对于原始的 JSON 字符串 str: { "id": 1000, "name": "ggicci", "birthday": [1991, 11, 10] }
JS: var str = '{ "id": 1000, "name": "ggicci", "birthday": [1991, 11, 10] }';
C++: const char* str = "{\"id\": 1000, \"name\": \"ggicci\", \"birthday\": [1991, 11, 10] }";
功能 | JS 的 JSON 解析器 | ggicci::Json(下面假设已声明使用命名空间 ggicci) |
解析并得到JSON对象 | var json = JSON.parse(str); |
Json json = Json::Parse(str); |
获取Number | var id = json["id"]; |
int id = json["id"]; |
获取String | var name = json["name"]; |
const char* name = json["name"]; string name = json["name"]; |
获取Array | var birthday = json["birthday"]; |
Json birthday = json["birthday"]; // 拷贝 Json &birthday = json["birthday"]; // 引用 Json *birthday = json["birthday"]; // 指针 |
ggicci::Json 中获取 null(需要通过 Json 对象,IsNull() 函数用来确定接收到的数据是否是 null) 获取Object(需要通过 Json 对象) 获取true,false(通过 bool 值就可以了) | ||
修改Number | json["id"] = 19214; |
json["id"] = 19214; |
修改String | json["name"] = "Mingjie Tang"; |
json["name"] = "Mingjie Tang"; |
修改Array | json["birthday"][2] = 11; |
json["birthday"][2] = 11; |
添加数据(Array) | json["birthday"].push(2013); json["birthday"].push("hello"); |
json["birthday"].Push(2013).Push("hello"); |
添加数据(Object) | json["man"] = true; |
json["man"] = true; json.AddProperty("man", true); |
删除数据(Array) | use pop, unshift ... | json["birthday"].Remove(0); // 不能级联 |
删除数据(Object) | delete json["name"]; |
json.Remove("name").Remove("id"); // 可以级联 |
获取Object的所有Keys | // 复杂 |
vector<string> keys = json.Keys(); |
异常处理
解析异常
int main(int argc, char const *argv[])
{
try
{
Json json = Json::Parse("[1, 2, 2, { \"id\": 183, \"name\": 'Ggicci' } ]");
}
catch (exception& e)
{
cout << e.what() << endl; // SyntaxError: Unexpected token ' at pos 31
}
return 0;
}
在 Chrome 下利用 JS 的 JSON::parse() 函数解析抛出的异常:
数据获取异常
int main(int argc, char const *argv[])
{
try
{
Json json = Json::Parse("[1, 2, 3, 4]");
int first = json[0]; // no problem
const char* second = json[1]; // cause exception
}
catch (exception& e)
{
cout << e.what() << endl; // OperationError: Illegal extract opeartion from Number to String
}
return 0;
}
非法操作异常
[cpp] view plain copy
int main(int argc, char const *argv[])
{
try
{
Json json = Json::Parse("[1, 2, 3, 4]");
json.AddProperty("name", "Ggicci"); // cause exception
}
catch (exception& e)
{
cout << e.what() << endl; // OperationError: Illegal add property opeartion on Array
}
return 0;
}
类型检测
[cpp] view plain copy
int main(int argc, char const *argv[])
{
Json json = Json::Parse("[1, \"hello\", { \"title\": null }, false ]");
json.IsArray(); // true
json[0].IsNumber(); // true
json[1].IsString(); // true
json[2].IsObject(); // true
json[2]["title"].IsNull(); //true
json[3].IsBool(); // true
if (json.IsArray())
{
for (int i = 0; i < json.Size(); ++i)
{
switch (json[i].DataKind())
{
case Json::kNumber: cout << "number: "; break;
case Json::kString: cout << "string: "; break;
case Json::kArray: cout << "array: "; break;
case Json::kObject: cout << "object: "; break;
case Json::kBool: cout << "bool: "; break;
case Json::kNull: cout << "null: "; break;
default: break;
}
cout << json[i] << endl;
}
}
return 0;
}
/*
output:
number: 1
string: "hello"
object: { "title": null }
bool: false
*/