"这不属于我,因为沉默背后,也有冲动"
一、认识json
(1) 为什么有那么多的数据交换格式?
比如说,现在我有下面的数据:
#include <iostream>
#include <string>
int main()
{
std::string name = "张三";
int age = 18;
std::string add = "China";
std::string email = "12321312@163.com";
return 0;
}
我想通过网路进行传输,这些从语言上来看定义出的数据,我该用什么样的方式。可是,一旦程序进行编译后,任何数据都是二进制代码,完全不便于人们进行观察。
因此,为了便于人阅读、编写,机器的生成和解析,json、protobuf等常见的数据交换格式接踵而至,在提高可读性的同时,有效提升了网络传输的效率。
(2) json简介
JSON 是一种轻量级的数据交换格式。采用完全独立于计算机语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。
取自这里
二、Jsoncpp
(1) Jsoncpp安装
# 查看自己库中是否安装了jsoncpp
rpm -qa | grep jsoncpp
如果没有,可以看看在yum源里查查看:
# 安装命令
sudo yum install -y jsoncpp-devel-0.10.5-2.el7.x86_64
安装完成后,我们可以在 /usr/include/jsoncpp路径下找到这些头文件:
usr/lib64 下的动静态库:
(2) Jsoncpp数据格式
这里我们想要表示一个学生的信息,用C语言表示:
char* name = "张三";
int age = 18;
float score[3] = {88.5,92.3,90.5};
如果我们用Json表示这一条语句呢:
{
"姓名":"张三";
"年龄":18,
"成绩": [85.5,92.3,90.3]
}
Json的数据类型包括对象,数组,字符串,数字等……
•对象: 使用花括号 {}
•数组: 使用中括号 []
•字符串: 使用常规的双引号("")
•数字:包括整形和浮点型,直接使⽤
(3) Jsoncpp接口介绍
Jsoncpp库主要用于json格式数据的 序列化 与 反序列化。
我们先来看看json对象的对象类表示:
class Json::Value{
//Value重载了[]和=,因此所有的赋值和获取
Value &operator=(const Value &other);
// "[]" 可以采用更简答的方式存储数据 val["name"] = xxx
Value& operator[](const char* key);
Value& operator[](const std::string& key);
Value removeMember(const char* key);//移除元素
// 数组访问 val["score"][0]
const Value& operator[](ArrayIndex index) const;
// 用于数组添加!
Value& append(const Value& value);//添加数组元素val["score"].append(88);
//获取数组元素个数
ArrayIndex size() const;
// 我们正常获得的是数据对象 而不是数据本身
// 但我们可以根据Value 获取数据本身
std::string asString() const;
const char* asCString() const;
Int asInt() const;
float asFloat() const;
bool asBool() const;
}
Jsoncpp 库主要借助三个类以及其对应的少量成员函数完成序列化及反序列化
• 序列化接⼝
// 这个是工厂函数 需要定义出来 new StreamWriter()
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
virtual StreamWriter* newStreamWriter() const;
}
class JSON_API StreamWriter {
virtual int write(Value const& root, std::ostream* sout) = 0;
}
• 反序列化接⼝:
// 同上
class JSON_API CharReaderBuilder : public CharReader::Factory {
virtual CharReader* newCharReader() const;
}
class JSON_API CharReader {
virtual bool parse(char const* beginDoc, char const* endDoc,
Value* root, std::string* errs) = 0;
}
我们完成了简单的json序列化反序列化接口的认识,我们"乘火打劫",写个简单的序列化反序列化代码。
三、 简易的序列化反序列化
序列化:
① 创建Json::Value 对象
② 创建工厂对象StreamWriterBuilder
③ 调用工厂函数对象方法 new StreamWriter() 获取序列化接口
④ 调用 write()接口
⑤ 获取序列化后的字符串返回
反序列化:
① 创建Json::Value 对象
② 创建工厂对象 CharReaderBuilder
③ 调用工厂函数对象方法 new CharReader() 获取序列化接口
④ 调用 parse()接口
⑤ 反序列化后的内容 在Json::Value的对象里
序列化:
对于write而言,都会返回0。如果感觉到数据序列化出错,相反应该检查stream流。
std::string serialization()
{
Json::Value root;
root["姓名"] = "张三";
root["年龄"] = 18;
root["成绩"].append(93.2);
root["成绩"].append(83.2);
root["成绩"].append(90.2);
Json::StreamWriterBuilder swb;
Json::StreamWriter* sw = swb.newStreamWriter();
// 是将root的对象数据序列化到一个字符串里
std::stringstream ss;
sw->write(root,&ss);
return ss.str();
}
反序列化:
bool deserialization(const std::string &str)
{
Json::Value root;
Json::CharReaderBuilder crb;
Json::CharReader* cr = crb.newCharReader();
std::string err;
bool ret = cr->parse(str.c_str(),str.c_str()+str.size(),&root,&err);
if(ret == false){
std::cout << "Json Parse Faild: " << err << std::endl;
return false;
}
// 访问root内容
std::cout << "姓名: " << root["姓名"].asCString() << std::endl;
std::cout << "年龄: " << root["年龄"].asInt() << std::endl;
int size = root["成绩"].size();
for(int i=0; i<size; ++i){
std::cout << "成绩" << i+1 << ": " << root["成绩"][i].asFloat() << std::endl;
}
return true;
}
本篇花了一些小篇幅讲了讲常用的数据交换格式:Json。
感谢你的阅读,
祝你好运,向阳而生~