首页 > Jsoncpp 在C++开发中的一些使用记录

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 : 
" << 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_ += "
";return document_;
}

StyledWriter::write

std::string StyledWriter::write(const Value& root) { document_ = "";addChildValues_ = false;indentString_ = "";writeCommentBeforeValue(root); // writeValue(root);writeCommentAfterValueOnSameLine(root);document_ += "
";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 
#include 
#include #include 
#include 
#include 
#include 
#include #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;
}

更多相关:

  • 经过长期探索,发现一个不需要手动设置线程休眠时间(e.g. std::this_thread::sleep_for(std::chrono::microseconds(1)))的代码: Github: https://github.com/log4cplus/ThreadPool #ifndef THREAD_POOL_H_7e...

  • nth_element(first,nth,last) first,last 第一个和最后一个迭代器,也可以直接用数组的位置。  nth,要定位的第nn 个元素,能对它进行随机访问. 将第n_thn_th 元素放到它该放的位置上,左边元素都小于它,右边元素都大于它. 测试代码: http://www.cplusplus.com...

  • c/c++老版本的rand()存在一定的问题,在转换rand随机数的范围,类型或者分布时,常常会引入非随机性。 定义在 中的随机数库通过一组协作类来解决这类问题:随机数引擎 和 随机数分布类 一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将(引擎和分布对象)定义为 st...

  • 问题如下: 已知一组数(其中有重复元素),求这组数可以组成的所有子集中,子 集中的各个元素和为整数target的子集,结果中无重复的子集。 例如: nums[] = [10, 1, 2, 7, 6, 1, 5], target = 8 结果为: [[1, 7], [1, 2, 5], [2, 6], [1, 1, 6]] 同样之前有...

  • importjava.security.SecureRandom;importjavax.crypto.Cipher;importjavax.crypto.SecretKey;importjavax.crypto.SecretKeyFactory;importjavax.crypto.spec.DESKeySpec;//结果与DES算...

  • 题目:替换空格 请实现一个函数,把字符串 s 中的每个空格替换成"%20"。 输入:s = "We are happy." 输出:"We%20are%20happy." 限制: 0 <= s 的长度 <= 10000 解题: 时间复杂度:O(n) 空间复杂度:O(n) class Solution { public:s...

  • 在C++11标准库中,string.h已经添加了to_string方法,方便从其他类型(如整形)快速转换成字面值。 例如: for (size_t i = 0; i < texArrSize; i++)RTX_Shader.SetInt(string("TexArr[") + to_string(i) + "]", 7 + i);...

  • Ubuntu 14.04安装并升级之后,变成楷体字体非常难看,我昨天搞了一晚上,终于理了个头绪,这里整理一下。 经过网上调研,大家的一致看法是,使用开源字体库文泉驿的微黑字体效果比较理想,甚至效果不输windows平台的雅黑字体。下面我打算微黑来美化Ubuntu 14.04. 1.安装文泉驿微黑字体库 sudo aptitude...

  • 使用string时发现了一些坑。 我们知道stl 容器并不是线程安全的,所以在使用它们的过程中往往需要一些同步机制来保证并发场景下的同步更新。 应该踩的坑还是一个不拉的踩了进去,所以还是记录一下吧。 string作为一个容器,随着我们的append 或者 针对string的+ 操作都会让string内部的数据域动态增加,而动态增加的...

  • 下面是我依据网上资料的实操过程,记录以作备忘。该示例给出了https通信并处理json文件的例子。 平台:Ubuntu 16.04.3 LTS go版本:1.10 1.生成自签名的服务器端的私钥KEY和公钥证书 openssl genrsa -out server.key 2048 openssl req -new -x509 -ke...

  • hive提供了json的解析函数:get_json_object   使用方法 对于jsonArray(json数组),如person表的xjson字段有数据: [{"name":"王二狗","sex":"男","age":"25"},{"name":"李狗嗨","sex":"男","age":"47"}] 取出第一个json对象...

  • 1、判断json是否为空 jQuery.isEmptyObject(); 2、遍历json function getHsonLength(json{var jsonLength=0;for (var i in json){jsonLength++;}return jsonLength;} 转载于:https...

  • 简单示例: import request from 'superagent';//引用声明 request.post(api).withCredentials()//跨域.end((err, res) => {if (res.ok) {const json = JSON.parse(res.text);} else {console...

  • 在使用C#开发爬虫程序时,会遇到需要解析json字符串的情况。对于json字符串可以使用正则表达式的形式进行解析,更为方便的方法是使用Newtonsoft.Json来实现。 Nuget添加应用包 在工程上右键——【管理Nuget程序包】浏览找到要安装的程序包Newtonsoft.Json使用 引用using Newtonsoft...