Jsoncpp 在C++开发中的一些使用记录
jsoncpp 是一個C++ 語言實現的json庫,非常方便得支持C++得各種數據類型到json 以及 json到各種數據類型的轉化。
一個json 類型的數據如下:
{"code" : 10.01,"files" : "","msg" : "","uploadid" : "UP000000"
}
這種數據類型方便我們人閱讀以及機器識別,因為將json類型的數據轉化為機器可識別的二進制串的過程就是一個json語法解析的狀態機狀態遷移的過程,對計算機比較友好。
所以基本大多數的高級編程語言都有對應的json庫,方便大家在大型項目中的數據傳輸以相同的數據類型進行交流。
這里可以看到其他語言的json庫列表:https://www.json.org/json-en.html
使用jsoncpp的過程中經jsoncpp 作為項目的第三方庫,并為需要使用json格式的頭文件包含
json/json.h即可。
Json 支持的數據類型
- signed integer [range: Value::minInt - Value::maxInt]
- unsigned integer (range: 0 - Value::maxUInt)
- double
- UTF-8 string
- boolean
- ‘null’
以及對應的字段轉化為相應類型的接口:
std::string asString()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;
Json 將字段解析為對應數據類型
如下方式進行json數據解析,并將解析出來的結果轉化為相應的數據類型。
// 輸入字符串形式的json串 轉化為js_value的json 對象。
// 輸入的buffer:
// std::string buffer = "{\"uploadid\": \"UP000000\",\"code\": 10.01,\"msg\": \"\",\"files\": \"\"}";
static void TestStringToJson(std::string buffer, Json::Value &js_value) {if (buffer.empty()) { return; } Json::Reader reader; if (reader.parse(buffer, js_value)) {// 將其中一個字段的數據轉化為double類型。double res = js_value["code"].asDouble(); std::cout << "Finish parse string to double: " << res << std::endl;// 另一個字段的結果轉化為string類型std::string upload = js_value["uploadid"].asString();std::cout << "Finish parse string: " << upload << std::endl;} else { std::cout << "Parse string to json failed!" << std::endl;}
}
最后的輸出如下
Finish parse string to double: 10.01
Finish parse string: UP000000
從 std::map 生成Json 數據類型
這個過程就類似構造key-value一樣,填充key,指定value即可。
如下函數:
inline void InitStatsMap() {AllStatsMap = {{1,10001},{2,20001},};
}std::map<uint64_t , std::string> StatsMap = {{1, "cpu.read.nanos"},{2, "cpu.write.nanos"}
};void TestJsonInsert() {Json::Value value;// 填充第一個字段的key 以及 對應的valuevalue["type"] = "kProfilingCPU";// 指定第二個字段"cpu"對應的key 的value也是一個json類型的字符串value["cpu"] = Json::objectValue;InitStatsMap();for (auto& pair: StatsMap) {value["cpu"][pair.second] = std::to_string(AllStatsMap[pair.first]);}std::cout << "Finish construct json form map : \n" << value << std::endl;
}
構建好的json 數據類型 輸出如下:
{"cpu" : {"cpu.read.nanos" : "10001","cpu.write.nanos" : "20001"},"type" : "kProfilingCPU"
}
Json數據類型轉化為string 數據類型
之前說過json支持的數據類型有string,同時也有這樣的asString()接口,但是這個接口僅僅是將json數據類型中的某一個key對應的field轉化為string,比如前面的value["uploadid"]對應的filed可以通過asString()接口取到,作為string來直接使用。
但是我們想要將整個Json數據類型轉化為string類型進行傳輸(http/restful 接口通信需要底層tcp需要傳輸char型的數據),則asString接口無法滿足,它需Json指定好對應的key才行。
jsoncpp支持如下兩種方式:
第一種: 通過FastWriter 按照語法來解析json類型,轉化為一個string
Json::FastWriter fast_writer;
std::string result = fast_writer.write(value);
std::cout << "json value: " << result << std::endl;
轉化后的輸出如下:
json value: {"cpu":{"cpu.read.nanos":"10001","cpu.write.nanos":"20001"},"type":"kProfilingCPU"}
第二種:通過value.toStyledString()
std::cout << "json value to string: " << value.toStyledString() << std::endl;
這種轉化后的輸出如下:
json value to string: {"cpu" : {"cpu.read.nanos" : "10001", "cpu.write.nanos" : "20001" }, "type" : "kProfilingCPU"
}
兩種都會轉化為string,只是最后的輸出形式上 第二種會保持json本身的形態,每一個字段結束之后都會有一個換行符。
相應的兩種writer的實現如下:
FastWriter::write
std::string FastWriter::write(const Value& root) {document_ = "";writeValue(root);if (!omitEndingLineFeed_)document_ += "\n";return document_;
}
StyledWriter::write
std::string StyledWriter::write(const Value& root) {document_ = "";addChildValues_ = false;indentString_ = "";writeCommentBeforeValue(root); // writeValue(root);writeCommentAfterValueOnSameLine(root);document_ += "\n";return document_;
}
講一個未知的Json字符串解析為其他數據類型
前面描述的json數據類型轉化為其他數據類型 其實都是我們知道json的一些field對應的key,所以我們可以通過value["xx"]方式獲取到所有的json數據。
但是實際使用過程中我們并不清楚傳輸過來的json字符串內容,所以需要能夠直接將json的內容解析成為我們想要的格式。
這個時候我們可以通過jsonvalue提供的迭代器來做這件事情:
inline static void JsonToMap(std::string buffer,std::unordered_map<std::string, std::string>& options_map) {if (buffer.empty()) {return;}Json::Value root;Json::Reader reader;// Get the json's element and insert it into options_mapif (reader.parse(buffer, root)) {for (Json::Value::iterator element = root.begin();element != root.end(); element ++) {if (!element.key().empty()) {options_map.insert({element.key().asString(), (*element).asString()});}}}return;
}
完整測試代碼
#include <stdio.h>
#include <string>
#include <unistd.h>#include <iostream>
#include <thread>
#include <cstring>
#include <unordered_map>
#include <map>#include "json/json.h"using namespace std;std::map<uint64_t , uint64_t> AllStatsMap;inline void InitStatsMap() {AllStatsMap = {{1,10001},{1,10002},{1,10003},{2,20001},{2,20002},{2,20003}};
}std::map<uint64_t , std::string> StatsMap = {{1, "cpu.read.nanos"},{2, "cpu.write.nanos"}
};void TestJsonInsert() {Json::Value value;value["type"] = "kProfilingCPU";value["cpu"] = Json::objectValue;InitStatsMap();for (auto& pair: StatsMap) {value["cpu"][pair.second] = std::to_string(AllStatsMap[pair.first]);}Json::FastWriter fast_writer;std::string result = fast_writer.write(value);std::cout << "json value: " << result << std::endl;std::cout << "json value to string: " << value.toStyledString() << std::endl;
}inline static void TestJsonToMap(std::string buffer,std::unordered_map<std::string, std::string>& options_map) {if (buffer.empty()) {return;}Json::Value root;Json::Reader reader;// Get the json's element and insert it into options.mapif (reader.parse(buffer, root)) {for (Json::Value::iterator element = root.begin();element != root.end(); element ++) {if (!element.key().empty()) {options_map.insert({element.key().asString(), (*element).asString()});}}}for (auto& op: options_map) {std::cout << op.first << " " << op.second << std::endl;}return;
}inline static void JsonToMap(std::string buffer,std::unordered_map<std::string, std::string>& options_map) {if (buffer.empty()) {return;}Json::Value root;Json::Reader reader;// Get the json's element and insert it into options.mapif (reader.parse(buffer, root)) {for (Json::Value::iterator element = root.begin();element != root.end(); element ++) {if (!element.key().empty()) {options_map.insert({element.key().asString(), (*element).asString()});}}}return;
}static void TestStringToJson(std::string buffer, Json::Value &js_value) {if (buffer.empty()) {return;}Json::Reader reader;if (reader.parse(buffer, js_value)) {std::cout << "Finish parse string to json: " << js_value << std::endl;std::string res = js_value["code"].asString();std::cout << "Finish parse string to double: " << res << std::endl;std::string upload = js_value["uploadid"].asString();std::cout << "Finish parse string: " << upload << std::endl;} else {std::cout << "Parse string to json failed!" << std::endl;}
}const std::string buffer = "{\"uploadid\": \"UP000000\",\"code\": 10.01,\"msg\": \"\",\"files\": \"\"}";
std::unordered_map<std::string, std::string> op_map;int main()
{TestJsonInsert();TestJsonToMap(buffer, op_map);Json::Value value;TestStringToJson(buffer, value);std::cout << "Json string to map with iterator : " << std::endl;std::unordered_map<std::string, std::string> mp;JsonToMap(buffer, mp);for (auto& pair : mp) {std::cout << pair.first << " " << pair.second << std::endl;}return 0;
}
總結
以上是生活随笔為你收集整理的Jsoncpp 在C++开发中的一些使用记录的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么都做试管婴儿
- 下一篇: “非惜年芳绝”上一句是什么