C++数据交换格式库jsoncpp安装与使用详解

一、json介绍

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使JSON成为理想的数据交换语言。

JSON建构于两种结构:

  • “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),纪录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。【name->value】
  • 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array)。

这些都是常见的数据结构。事实上大部分现代计算机语言都以某种形式支持它们。这使得一种数据格式在同样基于这些结构的编程语言之间交换成为可能。

JSON具有以下这些形式:
对象是一个无序的“‘名称/值’对”集合。一个对象以 {左括号 开始, }右括号 结束。每个“名称”后跟一个 :冒号 ;“‘名称/值’ 对”之间使用 ,逗号 分隔。

1.1 pair

先从键值对(pair)开始,一个pair的通常结构是:
key:value
键值之间的对应关系使用:表示,左边的为name,右边的为value。
一般key使用字符串,当然也可以使用数字,但是不推荐。
value的取值就比较随便,可以是任何任何json支持的类型(比如object,array,string,number,true/false,null等)。

1.2 object

object可以认为是多个pair的集合。
其语法是以{作为object开始,以}作为object结束,不同的pair之间使用,分割。
需要说明的是object中的数据存储是无序的。
示例:

{
"name" : "tocy",
"age" : 1000
}

1.3 array

array是value的有序集合。
其语法是以[作为array起始,以]作为array结束,array元素之间使用,分割。
实际使用中建议在array中使用统一的类型,否则解析起来会麻烦点。
比如下面语法是合法的:

[{"name":"tocy"}, {"age":1000}, {"domain":"cn"}]

参考链接:http://www.json.org/json-zh.html

二、jsoncpp库

我们都知道由于Json语法是 JavaScript 对象表示语法的子集。所以在Java,JavaScript等语言中使用起来是十分愉快的。在C++中我们使用跨平台的开源库JsonCpp也能愉快的玩耍Json。
JsonCpp 是一个C++库,允许操作 JSON 值,包括序列化和反序列化到字符串和从字符串反序列化。它还可以在非序列化/序列化步骤中保留现有注释,使其成为存储用户输入文件的便捷格式。

三、jsoncpp库下载、安装与使用

jsoncpp下载链接:https://github.com/open-source-parsers/jsoncpp

解压上面下载的jsoncpp-master.zip文件,把jsoncpp-master\include\json文件夹和jsoncpp-master\src\lib_json文件夹里的全部文件拷贝到工程目录下,并且添加到到VS工程中。
在需要使用JsonCpp的文件中包含json头文件即可,如:#include “json/json.h”。

四、jsoncpp常用类

在这里插入图片描述

4.1 Json::Value

Json::Value:可以表示所有支持的类型,如:int , double ,string , object, array等。其包含节点的类型判断(isNull,isBool,isInt,isArray,isMember,isValidIndex等),类型获取(type),类型转换(asInt,asString等),节点获取(get,[]),节点比较(重载<,<=,>,>=,==,!=),节点操作(compare,swap,removeMember,removeindex,append等)等函数。

4.2 Json::Reader

Json::Reader:将文件流或字符串创解析到Json::Value中,主要使用parse函数。Json::Reader的构造函数还允许用户使用特性Features来自定义Json的严格等级。

4.3 Json::Writer

Json::Writer:与JsonReader相反,将Json::Value转换成字符串流等,Writer类是一个纯虚类,并不能直接使用。在此我们使用 Json::Writer 的子类:Json::FastWriter(将数据写入一行,没有格式),Json::StyledWriter(按json格式化输出,易于阅读)。
Json::Reader可以通过对Json源目标进行解析,得到一个解析好了的Json::Value,通常字符串或者文件输入流可以作为源目标。

参考链接:http://jsoncpp.sourceforge.net/annotated.html

五、代码示例

创建一个json,命名为checkjson.json:

[
 { "name": "json",
  "lines": 
   [
    { "line": "1" },
    { "line": "2" },
    { "cpp": "jsoncpp" },
    { "java": "jsoninjava" },
    { "php": "support" }
   ]
 },
 { "name": "c++",
  "lines": 
   [
    { "line": "3" },
    { "line": "4" },
    { "cpp": "jsoncpp" },
    { "java": "jsoninjava" },
    { "php": "nosupport" }
   ]
 }
]

cpp代码如下:

#include <iostream>
#include <fstream>
#include <string>
#include "json/json.h"

using namespace std;
using namespace Json;

void main()
{
    //读取json文件
    fstream ofile("checkjson.json");
    string strjson;
    if (!ofile.is_open()) {
        return;
    }

    string strline;
    while (getline(ofile, strline)) {
        strjson += strline;
    }
    ofile.close();

    Json::Reader reader;  // 读取器
    Json::Value root;    // Value的值可以是任一对象

    if (reader.parse(strjson, root)) {

        int size = root.size();   // 根结点个数

        for (int j = 0; j < size; j++) {

            cout << root[j]["name"].asString() << endl;//输出key=name时的value

            const Json::Value arrayObj = root[j]["lines"];
            
            for (int i = 0; i < arrayObj.size(); i++) {

                if (arrayObj[i].isMember("line")) {
                    cout << arrayObj[i]["line"].asString() << endl;//输出key=line时的value
                }
                if (arrayObj[i].isMember("cpp")) {
                    cout << arrayObj[i]["cpp"].asString() << endl; //输出key = cpp时的value
                }
                if (arrayObj[i].isMember("java")) {
                    cout << arrayObj[i]["java"].asString() << endl;//输出key=java时的value
                }

            }
        }
    }
}

六、代码示例汇总

6.1 示例1:从文件中读取json文件并解析

首先我们提供一个json文件"checkjson.json",内容如下:

{
    "name" : "tocy",
    "age" : 1000
}

这里面保存的是最简单的object,我们可以使用下面代码将其读入并解析:

#include"json\json.h"
#include<iostream>
#include<string>
#include<fstream>
using namespace std;


void demo1_simple()
{
    ifstream ifs;
    ifs.open("checkjson.json");
    if (!ifs.is_open()) {
        cout << "open failed! \n";
        return;
    }

    Json::Reader reader;
    Json::Value root;
    if (!reader.parse(ifs, root, false))
    {
        cout << "parse failed! \n";
        return;
    }

    string name = root["name"].asString(); // 实际字段保存在这里
    int age = root["age"].asInt(); // 这是整型,转化是指定类型

    cout << "name:" << name << endl;
    cout << "age:" << age << endl;

}

int main()
{

    demo1_simple();

    return 0;
}

6.2 示例2:从内存中读取json数据(object)

我们在内存中定义一段json数据,然后解析,这次我们在json中添加内嵌array的object。代码如下:

void demo_parse_mem_object()
{
    const char json_data[] = 
        "{\"name\" : \"Tocy\", \"salary\" : 100, \"msg\" : \"work hard\", \
        \"files\" : [\"1.ts\", \"2.txt\"]}";  

    Json::Reader reader;
    Json::Value root;
    // reader将Json字符串解析到root,root将包含Json里所有子元素  
    if (!reader.parse(json_data, json_data + sizeof(json_data), root))
    {
        cerr << "json parse failed\n";
        return;
    }
    
    cout << "demo read from memory ---------\n";
    string name = root["name"].asString();
    int salary = root["salary"].asInt();
    string msg = root["msg"].asString();
    cout << "name: " << name << " salary: " << salary;
    cout << " msg: " << msg << endl;
    cout << "enter files: \n";
    Json::Value files = root["files"]; // read array here
    for (unsigned int i = 0; i < files.size(); ++i)
    {
        cout << files[i].asString() << " ";
    }
    cout << endl << endl;
}

6.3 从内存中解析json数据(array)

这次我们从提供一个以array封装的json数据,解析逻辑如下:

void demo_parse_mem_array()
{
    const char json_data[] = 
        "[{\"name\" : \"Tocy\", \"salary\" : 100}, {\"name\" : \"Kit\", \"salary\" : 89}, \
        \"a json note\"]";  

    Json::Reader reader;
    Json::Value root;
    // reader将Json字符串解析到root,root将包含Json里所有子元素  
    if (!reader.parse(json_data, json_data + sizeof(json_data), root))
    {
        cerr << "json parse failed\n";
        return;
    }
    
    cout << "demo read from memory using array---------\n";
    unsigned int count = root.size() - 1;
    for (unsigned int i = 0; i < count; ++i)
    {
        string name = root[i]["name"].asString();
        int salary = root[i]["salary"].asInt();
        cout << "name: " << name << " salary: " << salary << endl;
    }
    cout << "last msg: " << root[count].asString() << endl;
    cout << endl << endl;
}

6.4 简单json数据封装

前面三个是关于json数据解析的例子,下面是关于json数据封装的例子。
首先我们生成示例1的数据,代码如下:

void demo_write_simple()
{
    Json::Value root;
    Json::FastWriter writer;
    Json::Value person;
 
    person["name"] = "tocy";
    person["age"] = 1000;
    root.append(person);
 
    string json_file = writer.write(root);

    cout << "demo write json ==============\n";
    cout << json_file << endl;
}

6.5 json封装-内嵌array的object

生成示例2的数据,代码如下:

void demo_write_object()
{
    Json::Value root;
    Json::FastWriter writer;
 
    root["name"] = "tocy";
    root["salary"] = 100;
    root["msg"] = "work hard";
    Json::Value files;
    files[0] = "1.ts";
    files[1] = "2.txt";
    root["files"] = files;
 
    string json_file = writer.write(root);
    cout << "demo write json object ==============\n";
    cout << json_file << endl;
}

6.6 json封装-内嵌object的array

生成示例3的数据,代码如下:

void demo_write_array()
{
    Json::Value root;
    Json::FastWriter writer;

    {
        Json::Value person; 
        person["name"] = "Tocy";
        person["salary"] = 100;
        root[0] = person;
    }
    
    {
        Json::Value person; 
        person["name"] = "Kit";
        person["salary"] = 89;
        root[1] = person;
    }
    
    root[2] = "a json note";   
 
    string json_file = writer.write(root);
    cout << "demo write json ==============\n";
    cout << json_file << endl;
}

参考:

  1. https://www.jianshu.com/p/987e95cc79f4
  2. https://www.jb51.net/article/181816.htm
  3. https://www.cnblogs.com/tocy/p/json-intro_jsoncpp-lib.html
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

wendy_ya

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

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

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

打赏作者

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

抵扣说明:

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

余额充值