Jsoncpp 在C++开发中的一些使用记录
jsoncpp 是一個(gè)C++ 語言實(shí)現(xiàn)的json庫,非常方便得支持C++得各種數(shù)據(jù)類型到j(luò)son 以及 json到各種數(shù)據(jù)類型的轉(zhuǎn)化。
一個(gè)json 類型的數(shù)據(jù)如下:
{"code" : 10.01,"files" : "","msg" : "","uploadid" : "UP000000"
}
這種數(shù)據(jù)類型方便我們?nèi)碎喿x以及機(jī)器識(shí)別,因?yàn)閷son類型的數(shù)據(jù)轉(zhuǎn)化為機(jī)器可識(shí)別的二進(jìn)制串的過程就是一個(gè)json語法解析的狀態(tài)機(jī)狀態(tài)遷移的過程,對(duì)計(jì)算機(jī)比較友好。
所以基本大多數(shù)的高級(jí)編程語言都有對(duì)應(yīng)的json庫,方便大家在大型項(xiàng)目中的數(shù)據(jù)傳輸以相同的數(shù)據(jù)類型進(jìn)行交流。
這里可以看到其他語言的json庫列表:https://www.json.org/json-en.html
使用jsoncpp的過程中經(jīng)jsoncpp 作為項(xiàng)目的第三方庫,并為需要使用json格式的頭文件包含
json/json.h即可。
Json 支持的數(shù)據(jù)類型
- signed integer [range: Value::minInt - Value::maxInt]
- unsigned integer (range: 0 - Value::maxUInt)
- double
- UTF-8 string
- boolean
- ‘null’
以及對(duì)應(yīng)的字段轉(zhuǎn)化為相應(yīng)類型的接口:
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 將字段解析為對(duì)應(yīng)數(shù)據(jù)類型
如下方式進(jìn)行json數(shù)據(jù)解析,并將解析出來的結(jié)果轉(zhuǎn)化為相應(yīng)的數(shù)據(jù)類型。
// 輸入字符串形式的json串 轉(zhuǎn)化為js_value的json 對(duì)象。
// 輸入的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)) {// 將其中一個(gè)字段的數(shù)據(jù)轉(zhuǎn)化為double類型。double res = js_value["code"].asDouble(); std::cout << "Finish parse string to double: " << res << std::endl;// 另一個(gè)字段的結(jié)果轉(zhuǎn)化為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 數(shù)據(jù)類型
這個(gè)過程就類似構(gòu)造key-value一樣,填充key,指定value即可。
如下函數(shù):
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;// 填充第一個(gè)字段的key 以及 對(duì)應(yīng)的valuevalue["type"] = "kProfilingCPU";// 指定第二個(gè)字段"cpu"對(duì)應(yīng)的key 的value也是一個(gè)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;
}
構(gòu)建好的json 數(shù)據(jù)類型 輸出如下:
{"cpu" : {"cpu.read.nanos" : "10001","cpu.write.nanos" : "20001"},"type" : "kProfilingCPU"
}
Json數(shù)據(jù)類型轉(zhuǎn)化為string 數(shù)據(jù)類型
之前說過json支持的數(shù)據(jù)類型有string,同時(shí)也有這樣的asString()接口,但是這個(gè)接口僅僅是將json數(shù)據(jù)類型中的某一個(gè)key對(duì)應(yīng)的field轉(zhuǎn)化為string,比如前面的value["uploadid"]對(duì)應(yīng)的filed可以通過asString()接口取到,作為string來直接使用。
但是我們想要將整個(gè)Json數(shù)據(jù)類型轉(zhuǎn)化為string類型進(jìn)行傳輸(http/restful 接口通信需要底層tcp需要傳輸char型的數(shù)據(jù)),則asString接口無法滿足,它需Json指定好對(duì)應(yīng)的key才行。
jsoncpp支持如下兩種方式:
第一種: 通過FastWriter 按照語法來解析json類型,轉(zhuǎn)化為一個(gè)string
Json::FastWriter fast_writer;
std::string result = fast_writer.write(value);
std::cout << "json value: " << result << std::endl;
轉(zhuǎn)化后的輸出如下:
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;
這種轉(zhuǎn)化后的輸出如下:
json value to string: {"cpu" : {"cpu.read.nanos" : "10001", "cpu.write.nanos" : "20001" }, "type" : "kProfilingCPU"
}
兩種都會(huì)轉(zhuǎn)化為string,只是最后的輸出形式上 第二種會(huì)保持json本身的形態(tài),每一個(gè)字段結(jié)束之后都會(huì)有一個(gè)換行符。
相應(yīng)的兩種writer的實(shí)現(xiàn)如下:
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_;
}
講一個(gè)未知的Json字符串解析為其他數(shù)據(jù)類型
前面描述的json數(shù)據(jù)類型轉(zhuǎn)化為其他數(shù)據(jù)類型 其實(shí)都是我們知道json的一些field對(duì)應(yīng)的key,所以我們可以通過value["xx"]方式獲取到所有的json數(shù)據(jù)。
但是實(shí)際使用過程中我們并不清楚傳輸過來的json字符串內(nèi)容,所以需要能夠直接將json的內(nèi)容解析成為我們想要的格式。
這個(gè)時(shí)候我們可以通過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;
}
完整測(cè)試代碼
#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;
}
總結(jié)
以上是生活随笔為你收集整理的Jsoncpp 在C++开发中的一些使用记录的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 为什么都做试管婴儿
- 下一篇: 一个简单的程序来使用WiredTiger