1. 程式人生 > >Jsoncpp的使用

Jsoncpp的使用

比較 ber and ava 編譯鏈接 獲取json json.js sstream 之間

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)、truefalsenull、對象(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"節點,而後一種是輸出所有節點。

Jsoncpp的使用