快速体验c++读取json文件(jsoncpp)

一、参考资料

C++通过JsonCpp读取Json文件 - 山上有风景 - 博客园

【Json】——jsoncpp的序列化以及反序列化-CSDN博客

二、jsoncpp相关介绍

1. 概述

json-cpp download | SourceForge.net

jsoncpp的头文件所在目录:

jsoncpp/include/json

jsoncpp的lib库所在目录:

jsoncpp/src/lib_json

2. 数据类型

jsoncpp库常用源码解析及使用介绍(二)-CSDN博客

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::StyleWriterJson::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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花花少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值