一、参考资料
C++通过JsonCpp读取Json文件 - 山上有风景 - 博客园
【Json】——jsoncpp的序列化以及反序列化-CSDN博客
二、jsoncpp相关介绍
1. 概述
json-cpp download | SourceForge.net
jsoncpp的头文件所在目录:
jsoncpp/include/json
jsoncpp的lib库所在目录:
jsoncpp/src/lib_json
2. 数据类型
Json::Value
功能:创建json对象。
创建 key-value 数据:
Json::Value root;
root["key1"] = Json::Value("value1");
root["key2"] = Json::Value(1);
root["key3"] = Json::Value(false);
添加数组:
root["key_array"].append("string");
root["key_array"].append(22);
获取类型:
Json::ValueType type = root.type(); // 获取root的类型
类型判断
bool isNull() const; //判断JSON某一项是否为空
bool isBool() const; //判断JSON某一项是否是bool类型
bool isInt() const; //判断JSON某一项是否是int类型
bool isInt64() const; //判断JSON某一项是否是int64类型
bool isUInt() const; //判断JSON某一项是否是unsigned int类型
bool isUInt64() const; //判断JSON某一项是否是unsigned int64类型
bool isIntegral() const; //判断JSON某一项是否是整数
bool isDouble() const; //判断JSON某一项是否是double类型
bool isNumeric() const; //判断JSON某一项是否是数值类型
bool isString() const; //判断JSON某一项是否是string类型
bool isArray() const; //判断JSON某一项是否是数组类型
bool isObject() const; //判断JSON某一项是否是对象类型
bool isConvertibleTo(ValueType other) const; //判断JSON某一项是否能转换成other类型
类型转换
//声明
const char* asCString() const; //转换为const char*类型
String asString() const; //转换为string类型
Int asInt() const; //转换为int类型
UInt asUInt() const; //转换为unsigned int类型
Int64 asInt64() const; //转换为int64_t类型
UInt64 asUInt64() const; //转换为uint64_t类型
LargestInt asLargestInt() const; //转换为int64_t类型
LargestUInt asLargestUInt() const;//转换为uint64_t类型
float asFloat() const; //转换为float类型
double asDouble() const; //转换为double类型
bool asBool() const; //转换为bool类型
unsigned getCStringLength() const; //获取字符串长度
bool getString(char const** begin, char const** end) const; //获取原始字符串
3. Json::Write
Json::Writer为纯虚类,并不能直接使用。需要使用其子类:Json::FastWriter
(快,最常用)、Json::StyleWriter
、Json::StyleStreamWriter
。
Json::FastWriter
功能:快速输出Json数据。
#include <json/json.h>
using namespace std;
int main(){
Json::Value root;
root["key1"] = Json::Value("value1");
root["key2"] = Json::Value(1);
root["key3"] = Json::Value(false);
root["key_array"].append("string");
root["key_array"].append(22);
Json::FastWriter fwriter;
std::string jsonStr = fwriter.write(root);
cout << jsonStr << endl;
}
输出结果:
{"key1":"value1","key2":1,"key3":false,"key_array":["string",22]}
Json::StyleWriter
功能:格式化输出Json数据。
#include <json/json.h>
using namespace std;
int main(){
Json::Value root;
root["key1"] = Json::Value("value1");
root["key2"] = Json::Value(1);
root["key3"] = Json::Value(false);
root["key_array"].append("string");
root["key_array"].append(22);
Json::StyleWriter file;
cout << file.write(root) << endl;
}
输出结果:
{
"key1":"value1",
"key2":1,
"key3":false,
"key_array":["string",22]
}
4. 序列化与反序列化
基于C++、JsonCpp、Muduo库实现的分布式RPC通信框架-腾讯云开发者社区-腾讯云
序列化过程
功能:json转换为字符串。
jsoncpp的序列化是调用StreamWirter中的接口将Json::value转换为Json字符串。
函数原型:
class JSON_API StreamWriter {
virtual int write(Value const& root, std::ostream* sout) = 0;
}
class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
virtual StreamWriter* newStreamWriter() const;
}
解释说明:
StreamWriter
类中的write能够将Json::Value
对象转换为Json类型的字符串存放在sout
中。- 由于
StremWrtier
是一个抽象类,他不能直接定义出对象,需要先定义一个StreamWriterBuilder
类的对象,在通过newStreamWriter
接口定义StremWrtier
对象,才能使用writer接口。
简单示例:Jsoncpp序列化后并存储到 test.txt
文件中。
#include<iostream>
#include</usr/include/jsoncpp/json/json.h>
#include<fstream>
#include<sstream>
#include<memory>
using namespace std;
int main(){
char* name="sjp";
int age=18;
float scores[]={123.1,111,5,124.0};
Json::Value root;
//将变量定义到Json::value对象中
root["名字"]=name;
root["年龄"]=age;
root["成绩"].append(scores[0]);
root["成绩"].append(scores[1]);
root["成绩"].append(scores[2]);
//先定义StreamWriterBuilder对象
//在定义只能指针指向StreamWriter对象
Json::StreamWriterBuilder swb;
shared_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
//通过write将root序列化成Json字符串,并存储到str中
stringstream str;
sw->write(root,&str);
string s=str.str();
//将Json字符串输出到test.txt文件中
ofstream fstr;
fstr.open("test.txt",std::ios::binary);
fstr.write(s.c_str(),s.size());
fstr.close();
return 0;
}
反序列化过程
功能:字符串转换为json。
Jsoncpp的反序列化是调用CharReader是调用parse将Json类型的字符串转换到Json::Value对象中。
class JSON_API CharReader {
virtual bool parse(char const* beginDoc, char const* endDoc,
Value* root, std::string* errs) = 0;
}
class JSON_API CharReaderBuilder : public CharReader::Factory {
virtual CharReader* newCharReader() const;
}
解释说明:
CharReader
类中的parse接口能够将Json类型的字符串反序列化成Json::Value
对象并存放到root中,beginDoc
是字符串的起始位置,endDoc
是字符串的结束位置,errs
是接受错误信息。CharReader
是一个抽象类,不能直接定义出对象,需要先定义一个CharReaderBuilder
类的对象,再通过newCharReader()
接口创建一个CharReader
对象,才能使用parse()
接口
简单示例:打开 test.txt
文件,将文件中内容反序列化为 Json::value
对象中。
#include<iostream>
#include</usr/include/jsoncpp/json/json.h>
#include<fstream>
#include<sstream>
#include<memory>
using namespace std;
int main(){
//打开test.txt文件
ifstream ifs;
ifs.open("test.txt",std::ios::binary);
//获取文件的大小
ifs.seekg(0,ifs.end);
int length=ifs.tellg();
ifs.seekg(0,ifs.beg);
//将文件内容读取到s中
string s;
s.resize(length);
ifs.read(&s[0],length);
//对Json字符串进行反序列号并存储到root中
Json::CharReaderBuilder crb;
unique_ptr<Json::CharReader> cr(crb.newCharReader());
Json::Value root;
cr->parse(&s[0],&s[0]+s.size(),&root,nullptr);
//打印root中各个成员变量
cout<<root["名字"]<<endl;
cout<<root["年龄"]<<endl;
cout<<root["成绩"][0]<<endl;
cout<<root["成绩"][1]<<endl;
cout<<root["成绩"][2]<<endl;
return 0;
}
简单示例
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <jsoncpp/json/json.h>
// 实现数据的序列化
bool Serialize(const Json::Value& val, std::string& body)
{
std::stringstream ss;
// 先实例化一个工厂类对象
Json::StreamWriterBuilder swb;
// 通过工厂类对象来生产派生类对象
std::unique_ptr<Json::StreamWriter> sw(swb.newStreamWriter());
// 开始序列化
bool ret = sw->write(val, &ss);
if (ret != 0)
{
std::cout << "json serialize failed!" << std::endl;
return false;
}
body = ss.str();
return true;
}
// 实现json字符串的序列化
bool Unserialize(std::string &body, Json::Value &val)
{
// 实例化一个工厂类对象
Json::CharReaderBuilder crb;
// 生产派生类对象
std::unique_ptr<Json::CharReader> cr(crb.newCharReader());
std::string err;
bool ret = cr->parse(body.c_str(), body.c_str() + body.size(), &val, &err);
if (!ret)
{
std::cout << "json unserialize failed: " << err << std::endl;
return false;
}
return true;
}
int main()
{
const char* name = "小明";
int age = 18;
const char* sex = "男";
float score[3] = {88, 77.7f, 66};
Json::Value student;
student["姓名"] = name;
student["年龄"] = age;
student["性别"] = sex;
student["成绩"].append(score[0]);
student["成绩"].append(score[1]);
student["成绩"].append(score[2]);
Json::Value fav;
fav["书籍"] = "红楼梦";
fav["运动"] = "乒乓球";
student["爱好"] = fav;
std::string body;
if (Serialize(student, body))
std::cout << body << std::endl;
std::string str = R"({"姓名" : "小黑", "年龄" : 19, "成绩" : [66, 77, 88]})";
Json::Value stu;
bool ret = Unserialize(str, stu);
if (ret)
{
std::cout << "姓名: " << stu["姓名"].asString() << std::endl;
std::cout << "年龄: " << stu["年龄"].asInt() << std::endl;
for (auto e : stu["成绩"])
{
std::cout << "成绩: " << e.asFloat() << std::endl;
}
}
return 0;
}
三、c++读取json文件
apt安装jsoncpp
sudo apt-get install jsoncpp-devel
查看jsoncpp的头文件:
ls /usr/include/jsoncpp/json
查看jsoncpp的lib库:
ls /usr/lib64/libjson*
引用jsoncpp的头文件:
#include</usr/include/jsoncpp/json/json.h>
链接jsoncpp的lib库:
g++ test1.cpp -o test -ljsoncpp
2. 下载源码
json-cpp download | SourceForge.net
3. 拷贝jsoncpp到项目中
jsoncpp的头文件所在目录:
jsoncpp/include/json
jsoncpp的lib库所在目录:
jsoncpp/src/lib_json
将jsoncpp的头文件和cpp文件拷贝到项目目录:
mkdir ./third_party/jsoncpp
cp -r jsoncpp/include/json ./third_party/jsoncpp/
cp -r jsoncpp/src/lib_json ./third_party/jsoncpp/
项目结构:
yoyo@yoyo:/media/sda3/ProjectsC++/test_opencv-arm$ tree -L 4
.
├── json-demo
├── json-demo.cpp
├── test.json
└── third_party
└── jsoncpp
├── json
│ ├── allocator.h
│ ├── assertions.h
│ ├── config.h
│ ├── forwards.h
│ ├── json_features.h
│ ├── json.h
│ ├── reader.h
│ ├── value.h
│ ├── version.h
│ └── writer.h
└── lib_json
├── CMakeLists.txt
├── json_reader.cpp
├── json_tool.h
├── json_value.cpp
├── json_valueiterator.inl
└── json_writer.cpp
注意:其中json头文件目录不能修改名称,因为后面源文件引用格式 <json/...>,lib_json
源文件可以修改(也可以不用修改)
4. 简单示例
test.json
{
"name":"Mike Jiang",
"age":23,
"sex_is_male":true,
"partner":
{
"partner_name":"Galatea",
"partner_age":21,
"partner_sex_is_male":false
},
"achievement":["ach1","ach2","ach3"]
}
从文件中读取Json数据:
#include <string>
#include <json/json.h>
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
void readFileJson(); //从文件中读取Json
/*
@brief: 从Json文件中读取数据
编译x86版本:g++ json-demo.cpp ./third_party/jsoncpp/lib_json/*.cpp -I ./third_party/jsoncpp/ -o json-demo
编译arm版本:arm-linux-gnueabihf-g++ json-demo.cpp ./third_party/jsoncpp/lib_json/*.cpp -I ./third_party/jsoncpp/ -o json-dem
文件内容:
{
"name":"Mike Jiang",
"age":23,
"sex_is_male":true,
"partner":
{
"partner_name":"Galatea",
"partner_age":21,
"partner_sex_is_male":false
},
"achievement":["ach1","ach2","ach3"]
}
*/
void readFileJson()
{
Json::Reader reader;
Json::Value root;
ifstream in("test.json",ios::binary);
if(!in.is_open()){
cout<<"Error opening"<<endl;
return;
}
if(reader.parse(in,root)){
string name = root["name"].asString();
int age = root["age"].asInt();
bool sexIsM = root["sex_is_male"].asBool();
cout<<"My name is "<<name<<endl;
cout<<"I`m "<<age<<endl;
cout<<"I`m a"<<(sexIsM?"man":"woman")<<endl;
//读取子节点--字典
const Json::Value partner = root["partner"];
vector<string> keys = partner.getMemberNames();
for(unsigned int i=0;i<keys.size();i++){
cout<<partner[keys[i]];
}
//读取子节点--列表
const Json::Value achievement = root["achievement"];
for(unsigned int i=0;i<achievement.size();i++){
cout<<achievement[i].asString()<<endl;
}
}
in.close();
}
int main(int argc,char* argv[])
{
readFileJson();
return 0;
}
编译:
g++ json-demo.cpp ./third_party/jsoncpp/lib_json/*.cpp -I ./third_party/jsoncpp/ -o json-demo
执行:
/customer/json_test # ./json-demo
My name is Mike Jiang
I`m 23
I`m aman
21"Galatea"falseach1
ach2
ach3