JsonCpp 的使用
JSON全称为JavaScript ObjectNotation,它是一种轻量级的数据交换格式,易于阅读、编写、解析。jsoncpp是c++解析JSON串常用的解析库之一。
jsoncpp中主要的类:
Json::Value:可以表示所有支持的类型,如:int , double ,string , object, array等。其包含节点的类型判断(isNull,isBool,isInt,isArray,isMember,isValidIndex等),类型获取(type),类型转换(asInt,asString等),节点获取(get,[]),节点比较(重载<,<=,>,>=,==,!=),节点操作(compare,swap,removeMember,removeindex,append等)等函数。
Json::Reader:将文件流或字符串创解析到Json::Value中,主要使用parse函数。Json::Reader的构造函数还允许用户使用特性Features来自定义Json的严格等级。
Json::Writer:与JsonReader相反,将Json::Value转换成字符串流等,Writer类是一个纯虚类,并不能直接使用。在此我们使用 Json::Writer 的子类:Json::FastWriter(将数据写入一行,没有格式),Json::StyledWriter(按json格式化输出,易于阅读)
JsonCpp使用注意点:
1.对不存在的键获取值会返回此类型的默认值。
2.通过key获取value时,要先判断value的类型,使用错误的类型获取value会导致程序中断。
3.获取json数组中某一项key的value应该使用value[arraykey][index][subkey]获取或循环遍历数组获取。
4.append函数功能是将Json::Value添加到数组末尾。
5.由于Jsoncpp解析非法json时,会自动容错成字符类型。对字符类型取下标时,会触发assert终止进程。
解决方法:启用严格模式,让非法的json解析时直接返回false,不自动容错。这样,在调用parse的时候就会返回false。
Json::Reader *pJsonParser = new Json::Reader(Json::Features::strictMode());
判断json字符串中是否存在某键值的几种方法:
1.value.isMember("key"); //存在返回true,否则为false 2.value["sex"].isNull(); //为NULL返回1,否则为0
JsonCpp读写示例代码:
#include#include #include #include void readJsonFromFile() { std::ifstream ifs; ifs.open("a.json"); std::stringstream buffer; buffer << ifs.rdbuf(); ifs.close(); auto str = buffer.str(); Json::Reader reader; Json::Value value; if (reader.parse(str, value)) { //节点判断 std::cout << "value's empty:" << value.empty() << std::endl; std::cout << "name is string:" << value["name"].isString() << std::endl; std::cout << "age is string:" << value["age"].isString() << std::endl; //类型获取 std::cout << "name's type:" << value["name"].type() << std::endl; std::cout << "like's type:" << value["like"].type() << std::endl; //类型转换 //根据Key获取值时最好判断类型,否则解析会中断 std::cout << "name:" << value["name"].asString() << std::endl; std::cout << "age:" << value["age"].asInt() << std::endl; //节点获取 std::cout << value["job"] << std::endl; //[]方式获取 std::cout << value.get("name", "dxx") << std::endl; //get方式获取 std::cout << value.isMember("job") << std::endl; std::cout << "value's obj:" << value.isObject() << std::endl; std::cout << "like's obj:" << value["like"].isObject() << std::endl;
std::cout << "like.size:" << value["like"].size() << std::endl; std::cout << "like[0][food]:" << value["like"][0]["food"].asString() << std::endl; //节点操作 std::cout << "name compare age:" << value["name"].compare("age") << std::endl; value["name"] = "swduan"; //修改 value["address"] = "hz"; //增加 value["phone"] = "10086"; value.removeMember("age"); //删除 value["like"][0]["sport"] = "game"; //往value["like"]中添加一项元素 Json::Value item; item["hate"] = "game"; value["like"].append(item); //value["like"]中再添加一维数组 std::cout << "value[\"like\"]'s size:" << value["like"].size() << std::endl; std::cout << "--------------------" << std::endl; std::cout << value.toStyledString() << std::endl; std::cout << "--------------------" << std::endl; auto all_member = value.getMemberNames(); for (auto member : all_member) { std::cout << member << std::endl; } std::cout << "--------------------" << std::endl; value.clear(); //清空元素 std::cout << value.toStyledString() << std::endl; } } void jsonWriteToFile() { Json::FastWriter write; Json::Value root; Json::Value item; Json::Value arrayObj; item["book"] = "c++"; item["food"] = "apple"; item["music"] = "ddx"; arrayObj.append(item); root["name"] = "dsw"; root["age"] = 18; root["like"] = arrayObj; //注意:这里不能用append,append功能是将Json::Value添加到数组末尾 auto str = root.toStyledString(); std::cout << str << std::endl; std::ofstream ofss; ofss.open("a.json"); ofss << str; ofss.close(); } int main() { jsonWriteToFile(); readJsonFromFile(); getchar(); return 0; }
输出:
value's empty:0 name is string:1 age is string:0 name's type:4 like's type:6 name:dsw age:18 null "dsw" 1 value's obj:1 like's obj:0 like.size:1 like[0][food]:apple name compare age:1 value["like"]'s size:2 -------------------- { "address" : "hz", "job" : null, "like" : [ { "book" : "c++", "food" : "apple", "music" : "ddx", "sport" : "game" }, { "hate" : "game" } ], "name" : "swduan", "phone" : "10086" } -------------------- address job like name phone -------------------- {}
示例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;
}
» 下一篇: TinyXML2 的使用