JsonCpp學習-C++中處理Json

JsonCpp

瞭解何爲Json 參考資料如下.

JSON

JSON 教程 | 菜鳥教程

本節參考資料 jsoncpp的簡易教程 - Tudou_Blog - 博客園

一丶簡介

Json作爲一種文件格式,可以作爲配置文件使用.也可以作爲網絡傳輸使用. 而一些C/c++庫.

rapidjson jsoncpp cJSON等都是來解析這種文件的庫. 還有其它各種庫.都是大同小異.

這裏作爲學習貼來簡單的學習一下jsoncpp.

二丶JsonCpp環境配置.

首先先去 github下載jsoncpp的源碼 jsoncpp

下載後在本地顯示如下.

其中,我們想使用json的話,需要先進行 cmake編譯

jsoncpp是需要cmake編譯的.但是在高版本vs系列中.已經集成的cmake,不需要我們單獨下載.

需要打開各個編譯的器的命令行交叉編譯工具.

如: Vs xxx的 x64_86 交叉工具命令提示符.

打開後索引到jsoncpp的源碼目錄. 只需要執行命令.

cmake F:\xxx\jsoncpp\ 即可. 執行完畢之後在本層就會看到生成的cmake 文件夾.

打開後則可以看到有生成 jsoncpp.sln工程. 打開此工程. 圖片如下.

在裏面找到 jsoncpp_lib 工程. 可以按照自己需要將其編譯爲 靜態lib文件.或者dll文件. 默認是編譯的dll文件.且編譯方式是 MDD 和 MD 我們需要將其改爲. Realse(MT) Debug(MTD) 否則編譯出的DLL或者庫在別人電腦上用則會用不起來.別人電腦上會提示缺少DLL或者缺少xxx.

注意在編譯的時候,如果你要編譯爲lib.那麼需要 將配置類型改爲 靜態庫(.lib) 方式,且 目標文件擴展名要設置爲父類繼承,或者自己設置爲.lib. 這樣編譯的庫纔是正常的lib.

配置圖片.


三丶JsonCpp核心知識

3.1 JsonCpp的三個核心類

在JsonCpp中.提供了三個類.

說明
Json::Value 類型支持類,此類可以解析所有Json支持的類型.如: bool 字符串 浮點數 對象,以及 數組. 針對這些類型,還支持 isxxx來判斷.以及類型轉換.可以將類型裏面的值,按照json字段格式,轉爲相應的值. 如 value表示的是string節點.那麼asString則可以拿到此節點裏面的記錄的值.
Json::Reader 可以將文件,文件流,字符串內存,進行解析.解析的結果放到Json::Value中.剩下的時間我們就可以解析Json::Value了. 在JsonCpp新特性中,還允許用戶使用Features來定義Json的嚴格等級.這關乎到值解析失敗函數應該怎麼返回.
Json::Write 將數據轉化爲字符串流.也就是內存. 可以將內存寫入到文件. 此類是基類,我們必須使用它的實現子類,Json::FastWrite. 子類可以將Json進行壓縮.壓縮後寫入到文件.也可以使用 Json::StyledWrite子類. 可以指定自己喜愛的格式進行輸出.

3.2 Json::Value的引用和Json::Value

如果你使用 Json::Value& 接受的值. 那麼如果修改裏面的值.則其內存的json值會被修改.且其它代碼位置會被同步修改.

如果你使用的是 Json::Value. 那麼相當於只是一份副本. 修改副本里面的值不會影響到其它位置.

只需要知道一點,引用使用的是同一塊內存.一個地方改.那麼任何其它地方用到此塊內存的Json::Value都會被修改. 然 Json::Value值是副本.修改不會影響原始值.

3.3 使用JsonCpp

JsonCpp使用之前,需要從源碼文件中將Include拷貝出來.然後按照需要配置到自己的項目工程中. 如果是編譯的進程庫.那麼需要引入靜態庫.

配置方式有多種.

1.直接將Include放到自己項目文件夾下.將其Lib也是放到自己項目文件夾下.然後添加頭文件,將所有的頭文件加入到自己工程中.

2.可以在項目工程中的 Vc++目錄中指定要包含的目錄,以及引用的目錄.

lib庫的引用可以配置在 連接器裏面的引用庫目錄中. (這屬於Vs項目基礎知識.不懂可以百度搜索)

四丶學習JsonCpp中Value類中的函數.

3.1 JsonCpp值獲取函數.

asxxx是JsonCpp中的類型值獲取函數.如 Json字段如果是 字符串.那麼則可以使用 asString將其轉換爲std::string.

 const char* asCString() const;
  unsigned getCStringLength() const; 
  String asString() const; 
  bool getString(char const** begin, char const** end) const;
  Int asInt() const;
  UInt asUInt() const;
#if defined(JSON_HAS_INT64)
  Int64 asInt64() const;
  UInt64 asUInt64() const;
#endif // if defined(JSON_HAS_INT64)
  LargestInt asLargestInt() const;
  LargestUInt asLargestUInt() const;
  float asFloat() const;
  double asDouble() const;
  bool asBool() const;

3.2 JsonCpp值類型判斷函數

isxxx 可以判斷當前值是否是對應類型.

  bool isNull() const;
  bool isBool() const;
  bool isInt() const;
  bool isInt64() const;
  bool isUInt() const;
  bool isUInt64() const;
  bool isIntegral() const;
  bool isDouble() const;
  bool isNumeric() const;
  bool isString() const;
  bool isArray() const;
  bool isObject() const;

3.3 JsonCpp中數組操作函數

ArrayIndex = unsigned int.

  Value get(ArrayIndex index, const Value& defaultValue) const; 傳入index獲取數組元素
  bool isValidIndex(ArrayIndex index) const;//判斷指定index是否有效
  Value& append(const Value& value); //添加數組元素
  Value& append(Value&& value);      
  bool insert(ArrayIndex index, const Value& newValue); //傳入index插入數組元素
  bool insert(ArrayIndex index, Value&& newValue);
  bool removeIndex(ArrayIndex index, Value* removed);//刪除指定index,刪除的元素會通過參數2返回
  bool empty() const; //數組爲空 對象爲空 或者是 null 返回true
  void clear(); 如果是數組則清空所有元素,如是對象,則刪除所有對象members.
  void resid(ArrayIndex newSize); 將數組元素擴充至N

3.4 JsonCpp中的對象操作

Members = vector<string>

 Members getMemberNames() const; //獲取對象下面記錄的所有key,返回值是一個vector<string)
 bool isMember(const char* key) const; //三個重載函數,判斷值是否是member
 bool isMember(const String& key) const;
 bool isMember(const char* begin, const char* end) const;
 重載函數,刪除對象裏面的執行member. 根據重載函數,可以接受返回的值.
  void removeMember(const char* key);
  void removeMember(const String& key);
  bool removeMember(const char* key, Value* removed);
  bool removeMember(String const& key, Value* removed);
  bool removeMember(const char* begin, const char* end, Value* removed);

獲取和查找

根據c字符串的key 查找 value
Value get(const char* key, const Value& defaultValue) const;
//根據迭代器查找value
Value get(const char* begin, const char* end,
            const Value& defaultValue) const;
//根據C++的string key獲取
Value get(const String& key, const Value& defaultValue) const;
//進行查找
Value const* find(char const* begin, char const* end) const;

3.5 JsonCpp中的 運算符重載.

在JsonCpp中重載了[] .使我們可以在解析Json的時候可以按照數組方式解析. 當然還進行了增強.可以輸入字符串.則JsonCpp會訪問此節點.

示例僞代碼如下

Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
//示例
Json::Value& settings = root["A"]["B"]["C"];
Json::Value& settings = root[1][2]["C"].asString();

其它重載還有很多. .如 < <= > >= == !=

3.6 JsonCpp中的迭代器.

迭代器使我們可以去遍歷 Json::Value. 而Json::Value存儲的是Json數據.相當於我們可以直接按照自己喜歡的方式去遍歷Json數據.

提供的迭代器如下

 const_iterator begin() const; //常量迭代器 只能遍歷值,而不能修改裏面的值
 const_iterator end() const;

 iterator begin(); //迭代器,可以修改裏面的值.
 iterator end();

3.7 JsonCpp的Json串轉化

可以將字符串轉爲Json串.主要使用Value類中的一個函數.可以將一個Value值轉爲一個格式化的字符串.

如果想將字符串壓縮.或者只是想獲取壓縮的字符串.那麼請使用 第五節所講的 Json::Write的實現類.

String Value::toStyledString() const

五丶學習JsonCpp中的Json::Reader和Json::Write類

5.1 反序列化 - 解析函數

bool parse(const std::string& document, Value& root,
             bool collectComments = true);
bool parse(const char* beginDoc, const char* endDoc, Value& root,
             bool collectComments = true);
bool parse(IStream& is, Value& root, bool collectComments = true);

解析函數有三個重載, 可以解析 字符串流. 可以解析文件流. 也可以解析begindoc以及enddoc(我未用過) 解析的結果保存在 Jsn::Value中.

示例:

std::string json_data = 從文件中讀取的數據.爲了代碼簡介省去文件讀寫.

Json::Reader reader;
Json::Value root;
reader.parse(json_data, root);

5.2 序列化-寫入

Json::Write有許多實現的子類.常用的子類如下.

  Json::StyledWriter styled_write;//格式化json
  Json::FastWriter pack_write; //只是將value轉化爲壓縮的內存數據

用法.

 pack_writ.write(root);
 //結果:
 {"a":1,"b":2}
 styled_write.write(root);
 //結果
 {
     "a":1,
     "b":2
 }

六丶JsonCpp的實戰操作.

6.1 JsonCpp 對象操作.

設Json值 = 如下.

{
    "active_bit": false,
    "active_permissions": {
        "api": ["activeTab", "contextMenus", "storage"],
        "explicit_host": [],
        "manifest_permissions": [],
        "scriptable_host": ["\u003Call_urls>"]
    },

    "granted_permissions": {
        "api": ["activeTab", "contextMenus", "storage"],
        "explicit_host": [],
        "manifest_permissions": [],
        "scriptable_host": ["\u003Call_urls>"]
    },

    "last_update_time": "13324124641142852",
    "lastpingday": "13324114818159590",
    "location": 1,
    "state": 1,
    "was_installed_by_default": false,
    "was_installed_by_oem": false,
    "withholding_permissions": false
}

代碼如下.

void ParseJsonObject(Json::Value& root)
{


  //1. 獲取對象裏面的所有 key值. 也就是name
  //auto member = xxx 也是可以的.
  //member其實是一個 std::vector<string>類型.可以按照自己喜歡的迭代方式進行迭代.
  Json::Value::Members member = root.getMemberNames();
  for (int i = 0; i < member.size(); i++)
  {
    cout << member[i].c_str() << endl;
  }

  //2.獲取指定key值. 並且獲取實際值.
  Json::Value last_update_time = root["last_update_time"];
  std::string last_update_time_str = last_update_time.asString();

  //3.通過遍歷方式,找到指定key值.並且修改裏面的值.
  for (int i = 0; i < member.size(); i++)
  {
    if (member[i].compare("location") != std::string::npos)
    {
      root[member[i]] = 3;
    }
  }
  cout << root["location"].toStyledString() << endl;
  //4.創建一個對象
 Json::Value object;
  object["a"] = "1";
  object["b"] = "2";
  object["c"] = 3;
  object["d"] = true;
  object["f"] = 3.14;

  std::string test = object.toStyledString();
  cout << test << endl;

}
int main()
{


  //JsonCppObj jsoncppobj;
  Json::Reader reader;
  Json::Value  root;
  std::string json_data = R"({
    "active_bit": false,
    "active_permissions": {
        "api": ["activeTab", "contextMenus", "storage"],
        "explicit_host": [],
        "manifest_permissions": [],
        "scriptable_host": ["\u003Call_urls>"]
    },

    "granted_permissions": {
        "api": ["activeTab", "contextMenus", "storage"],
        "explicit_host": [],
        "manifest_permissions": [],
        "scriptable_host": ["\u003Call_urls>"]
    },

    "last_update_time": "13324124641142852",
    "lastpingday": "13324114818159590",
    "location": 1,
    "state": 1,
    "was_installed_by_default": false,
    "was_installed_by_oem": false,
    "withholding_permissions": false
}
)";

  reader.parse(json_data, root);
  ParseJsonObject(root);



  return 1;

}

輸出結果如下


active_bit
active_permissions
granted_permissions
last_update_time
lastpingday
location
state
was_installed_by_default
was_installed_by_oem
withholding_permissions


3


{
        "a" : "1",
        "b" : "2",
        "c" : 3,
        "d" : true,
        "f" : 3.1400000000000001
}
*/

6.2 JsonCpp中的數組操作.

void ParseJsonArray(Json::Value& root)
{

  //1.創建對象數組
  Json::Value array;
  Json::Value array_item;
  array_item.append(1);
  array_item.append(2);
  array_item.append(3);
  array_item.append(4);
  array_item.append(5);
  array["test_ary"] = array_item;

  std::string test = array.toStyledString();
  cout << test << endl;

  //2.第二種方式創建數組
  // 

  Json::Value array_two;
  array_two[0] = "z";
  array_two[1] = 2;
  array_two[2] = true;
  array_two[3] = false;
  array_two[4] = 3.14f; //float
  array_two[5] = 7.23;  //double
  cout << array_two.toStyledString() << endl;
  //3.遍歷數組  解析數組
  Json::Value api_array = root["active_permissions"]["api"];
  for (int i = 0; i < api_array.size(); i++)
  {
    if (api_array[i].isString())
    {
      cout << api_array[i].asString().c_str() << endl;
    }
  }

}

輸出結果如下:

{
        "test_ary" :
        [
                1,
                2,
                3,
                4,
                5
        ]
}

[
        "z",
        2,
        true,
        false,
        3.1400001049041748,
        7.2300000000000004
]

activeTab
contextMenus
storage

6.3 其它.

其實json中大部分都是 Object嵌套基礎類型.或者嵌套 Array. 只需要我們一層一層解析即可.

所以熟悉6.1 6.2小結完全夠用.其它都是基礎Value類型. 其中對於Object和Array還應有增刪改查例子.其實還是函數的使用. 瞭解了JsonCpp的大體設計思想之後.只需要學習函數即可.

我也是花了半天時間熟悉了下JsonCpp寫出了此篇文章. 而已經能解決複雜Json.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章