Jsoncpp的使用
来源 https://www.cnblogs.com/kex1n/archive/2011/12/02/2272328.html
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。
JSON建构于两种结构:
- “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。
- 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。
这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。
JSON具有以下这些形式:
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。

数组是值(value)的有序集合。一个数组以“[”(左中括号)开始,“]”(右中括号)结束。值之间使用“,”(逗号)分隔。

值(value)可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。

字符串(string)是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。一个字符(character)即一个单独的字符串(character string)。
字符串(string)与C或者Java的字符串非常相似。

数值(number)也与C或者Java的数值非常相似。除去未曾使用的八进制与十六进制格式。除去一些编码细节。

空白可以加入到任何符号之间。 以下描述了完整的语言。
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 <iostream>
#include <sstream>
#include <fstream>
#include <json/json.h>
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
--------------------
{}
C++要使用JSON来解析数据,一般采用jsoncpp.
网站:http://sourceforge.net/projects/jsoncpp/
下载了之后,解压,然后打开\jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\makefiles\vs71
下的工程文件,进行编译链接就可以得到一个静态链接库json.lib
要用jsoncpp只需要将这个lib文件拷贝到你的工程目录下,并将jsoncpp-src-0.5.0\jsoncpp-src-0.5.0\include\json
复制到工程目录下,然后将这些头文件加到工程中去就可以了。
例子:
{
"name" : "小楼一夜听春雨",
"age" : 27
}
#pragma comment(lib, "json_mtd.lib") #include <fstream> #include <cassert> #include "json/json.h" int main() { ifstream ifs; ifs.open("testjson.json"); assert(ifs.is_open()); Json::Reader reader; Json::Value root; if (!reader.parse(ifs, root, false)) { return -1; } std::string name = root["name"].asString(); int age = root["age"].asInt(); std::cout<<name<<std::endl; std::cout<<age<<std::endl; return 0; }
[{"name" : "xiaoy", "age" :17} , {"name" : "xiaot", "age" : 20}]
#pragma comment(lib, "json_mtd.lib") #include <fstream> #include <cassert> #include "json/json.h" int main() { ifstream ifs; ifs.open("testjson.json"); assert(ifs.is_open()); Json::Reader reader; Json::Value root; if (!reader.parse(ifs, root, false)) { return -1; } std::string name; int age; int size = root.size(); for (int i=0; i<size; ++i) { name = root[i]["name"].asString(); age = root[i]["age"].asInt(); std::cout<<name<<" "<<age<<std::endl; } return 0; }
json写入:
#pragma comment(lib, "json_mtd.lib") #include <fstream> #include <cassert> #include "json/json.h" int main() { Json::Value root; Json::FastWriter writer; Json::Value person; person["name"] = "hello world"; person["age"] = 100; root.append(person); std::string json_file = writer.write(root); ofstream ofs; ofs.open("test1.json"); assert(ofs.is_open()); ofs<<json_file; return 0; }
结果:[{"age":100,"name":"hello world"}]
json对数组的解析还支持STL的风格。即
Json::Value::Members member;//Members 这玩意就是vector<string>,typedef了而已 for (Json::Value::iterator itr = objArray.begin(); itr != objArray.end(); itr++) { member = (*itr).getMemberNames(); for (Json::Value::Members::iterator iter = member.begin(); iter != member.end(); iter++) { string str_temp = (*itr)[(*iter)].asString(); } }
此种风格与上面的类似,只是上面的只是取"text"节点,而后一种是输出所有节点。
