Linux(程序设计):31---jsoncpp库(C++操作JSON)

Posted 董哥的黑板报

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux(程序设计):31---jsoncpp库(C++操作JSON)相关的知识,希望对你有一定的参考价值。

一、jsoncpp库概述

库的安装

sudo apt-get install libjsoncpp-dev

  • 安装完成之后,头文件默认安装在/usr/include/jsoncpp/json/目录下,库API文档默认在/usr/share/doc/libjsoncpp-dev/目录下

编译带有jsoncpp库的C++程序

  • 使用如下的命令进行编译,编译时带上-ljsoncpp选项即可
  • 例如:
g++ jsoncpp_demo01.c -o demo01 -ljsoncpp -std=c++11
二、jsoncpp支持的值
  • jsoncpp 使用 Json::Value 对象来保存 JSON 串,Json::Value 对象可以表示如下数据类 型:

三、相关接口

检测保存的数据类型

bool isNull() const;
bool isBool() const;
bool isInt() const;
bool isInt64() const;
bool isUInt() const;
bool isUInt64() const;
bool isIntegral() const;
bool isDouble() const;
bool isNumeric() const;
bool isString() const;
bool isArray() const;
bool isObject() const;

基础数据类型的访问

const char* asCString() const;
JSONCPP_STRING asString() const;
Int asInt() const;
UInt asUInt() const;
Int64 asInt64() const;
UInt64 asUInt64() const;
LargestInt asLargestInt() const;
LargestUInt asLargestUInt() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;

数组风格

  • ValueType::arrayValue 和 ValueType::objectValue 数据类型的访问,操作方式很类似 C++的 vector,可以使用数组风格或者迭代器风格来操作数据。例如:
root["name"] = "milo";
  • 下面是相关接口
ArrayIndex size() const;
Value& operator[](ArrayIndex index);
Value& operator[](int index);
const Value& operator[](ArrayIndex index) const;
const Value& operator[](int index) const;
Value get(ArrayIndex index, const Value& defaultValue) const;
const_iterator begin() const;
const_iterator end() const;
iterator begin();
iterator end();
  • ValueType::objectValue 数据类型的访问,操作方式很类似 C++的 map
Value& operator[](const char* key);
const Value& operator[](const char* key) const;
Value& operator[](const JSONCPP_STRING& key);
const Value& operator[](const JSONCPP_STRING& key) const;
Value& operator[](const StaticString& key);
Value& operator[](const CppTL::ConstString& key);
const Value& operator[](const CppTL::ConstString& key) const;
Value get(const char* key, const Value& defaultValue) const;
Value get(const char* begin, const char* end, const Value& defaultValue) const;
Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;

修改数据

  • 知道如何获取 Json::Value 对象或其子对象后,我们来看下如何修改 Json::Value 保存 的数据:
  • 直接使用=赋值就可以了
Value& operator=(Value other);
  • 因为 Json::Value 已经实现了各种数据类型的构造函数
Value(ValueType type = nullValue);
Value(Int value);
Value(UInt value);
Value(Int64 value);
Value(UInt64 value);
Value(double value);
Value(const char* value);
Value(const char* begin, const char* end);
Value(const StaticString& value);
Value(const JSONCPP_STRING& value);
Value(const CppTL::ConstString& value);
Value(bool value);
Value(const Value& other);
Value(Value&& other);
四、注意事项

类型转换

  • 对于Int、Uint、Int64、UInt64等类型,注意类型。
root["age"] = 80;  //默认为Int类型
  • 可以使用下面的方式进行强制类型转换
root["age"] = (Json::Uint)80;

空值

  • 如果要将变量设置为 null,应该使用如下的方式
root["address"] = Json::nullValue;
五、演示案例1

代码如下

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

int main()
{
    std::cout << "Hello World!" << std::endl;

    Json::Value root;
    Json::FastWriter fast;

    root["ModuleType"] = Json::Value(1);
    root["ModuleCode"] = Json::Value("China");

    std::cout<<fast.write(root)<<std::endl;

    Json::Value sub;
    sub["version"] = Json::Value("1.0");
    sub["city"] = Json::Value(root);
    fast.write(sub);

    std::cout<<sub.toStyledString()<<std::endl;

    return 0;
}
  • 编译运行如下: 
g++ jsoncpp_demo01.c -o demo01 -ljsoncpp -std=c++11

六、演示案例2

代码如下

#include <string>
#include <jsoncpp/json/json.h>
#include <iostream>
 
using namespace std;
 
void readJson() {
	std::string strValue = "{\\"name\\":\\"json\\",\\"array\\":[{\\"cpp\\":\\"jsoncpp\\"},{\\"java\\":\\"jsoninjava\\"},{\\"php\\":\\"support\\"}]}";
 
	Json::Reader reader;
	Json::Value value;
 
	if (reader.parse(strValue, value))
	{
		std::string out = value["name"].asString();
		std::cout << out << std::endl;
		const Json::Value arrayObj = value["array"];
		for (unsigned int i = 0; i < arrayObj.size(); i++)
		{
			if (!arrayObj[i].isMember("cpp")) 
				continue;
			out = arrayObj[i]["cpp"].asString();
			std::cout << out;
			if (i != (arrayObj.size() - 1))
				std::cout << std::endl;
		}
	}
}

void writeJson() {
 
	Json::Value root;
	Json::Value arrayObj;
	Json::Value item;
 
	item["cpp"] = "jsoncpp";
	item["java"] = "jsoninjava";
	item["php"] = "support";
	arrayObj.append(item);
 
	root["name"] = "json";
	root["array"] = arrayObj;
 
	root.toStyledString();
	std::string out = root.toStyledString();
	std::cout << out << std::endl;
}

int main(int argc, char** argv) {
	readJson();
	writeJson();
	return 0;
}
  • 编译运行如下:  
g++ jsoncpp_demo02.c -o demo02 -ljsoncpp -std=c++11

七、演示案例3

代码如下

//测试jsoncpp的使用方法和性能
#include <memory>
#include <sstream>
#include <iostream>
#include <stdint.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "jsoncpp/json/json.h"
#include "jsoncpp/json/value.h"
#include "jsoncpp/json/reader.h"
#include "jsoncpp/json/writer.h"

/*

{
  "name": "milo",
  "age": 80,
  "languages": ["C++", "C"],
  "phone": {
    "number": "186****3143",
    "type": "home"
  },
  "books":[
      {
          "name": "Linux kernel development",
          "price":7.7
      },
      {
          "name": "Linux server development",
          "price": 8.0
      }
  ],
  "vip":true,
  "address": null
}
 */

static uint64_t getNowTime()
{
    struct timeval tval;
    uint64_t nowTime;

    gettimeofday(&tval, NULL);

    nowTime = tval.tv_sec * 1000L + tval.tv_usec / 1000L;
    return nowTime;
}

std::string JsoncppEncodeNew()
{
    std::string jsonStr;
    // 一个value是可以包含多个键值对
    Json::Value root, languages, phone, book, books;

    // 姓名
    root["name"] = "milo";
    // 年龄
    root["age"] = 80;

    // 语言
    languages[0] = "C++";
    languages[1] = "Java";
    root["languages"] = languages;

    // 电话
    phone["number"] = "186****3143";
    phone["type"] = "home";
    root["phone"] = phone;

    // 书籍
    book["name"] = "Linux kernel development";
    book["price"] = 7.7;
    books[0] = book;    // 深拷贝
    book["name"] = "Linux server development";
    book["price"] = 8.0;
    books[1] = book;    // 深拷贝
    root["books"] = books;

    // 是否为vip
    root["vip"] = true;

    // address信息空null
    root["address"] = "yageguoji";

    Json::StreamWriterBuilder writerBuilder;
    std::ostringstream os;
    std::unique_ptr<Json::StreamWriter> jsonWriter(writerBuilder.newStreamWriter());
    jsonWriter->write(root, &os);
    jsonStr = os.str();

    // std::cout << "Json:\\n" << jsonStr << std::endl;
    return jsonStr;
}

std::string JsoncppEncodeOld()
{
    std::string jsonStr;
    Json::Value root, languages, phone, book, books;

    // 姓名
     root["name"] = "milo";
    //root["name"] = Json::nullValue;
    // 年龄
    root["age"] =  80; 

    // 语言
    languages[0] = "C++";
    languages[1] = "Java";
    root["languages"] = languages;

    // 电话
    phone["number"] = "186****3143";
    phone["type"] = "home";
    root["phone"] = phone;

    // 书籍
    book["name"] = "Linux kernel development";
    book["price"] = (float)7.7;
    books[0] = book;
    book["name"] = "Linux server development";
    book["price"] = (float)8.0;
    books[1] = book;
    root["books"] = books;

    // 是否为vip
    root["vip"] = true;

    // address信息空null
    root["address"] = "yageguoji"; //;// Json::nullValue; // 如果是null,则要用自定义的Json::nullValue,不能用NULL

    Json::FastWriter writer;
    jsonStr = writer.write(root);

    // std::cout << "Json:\\n" << jsonStr << std::endl;
    return jsonStr;
}

// 不能返回引用
Json::Value JsoncppEncodeOldGet()
{
    Json::Value root;
    Json::Value languages, phone, book, books;

    // 姓名
    root["name"] = "milo";
    //root["name"] = Json::nullValue;
    // 年龄
    root["age"] =  80; 

    // 语言
    languages[0] = "C++";
    languages[1] = "Java";
    root["languages"] = languages;

    // 电话
    phone["number"] = "186****3143";
    phone["type"] = "home";
    root["phone"] = phone;

    // 书籍
    book["name"] = "Linux kernel development";
    book["price"] = (float)7.7;
    books[0] = book;
    book["name"] = "Linux server development";
    book["price"] = (float)8.0;
    books[1] = book;
    root["books"] = books;

    // 是否为vip
    root["vip"] = true;

    // address信息空null
    root["address"] = Json::nullValue; //"yageguoji";// Json::nullValue; // 如果是null,则要用自定义的Json::nullValue,不能用NULL

 

    std::cout << "JsoncppEncodeOldGet:\\n"  << std::endl;
    return root;
}

void printJsoncpp(Json::Value &root)
{
    if(root["name"].isNull())
    {
        std::cout << "name null\\n";
    }
    std::cout << "name: " << root["name"].asString() << std::endl;
    std::cout << "age: " << root["age"].asInt() << std::endl;

    Json::Value &languages = root["languages"];
    std::cout << "languages: ";
    for (uint32_t i = 0; i < languages.size(); ++i)
    {
        if (i != 0)
        {
            std::cout << ", ";
        }
        std::cout << languages[i].asString();
    }
    std::cout << std::endl;

    Json::Value &phone = root["phone"];
    std::cout << "phone number: " << phone["number"].asString() << ", type: " << phone["type"].asString() << std::endl;

    Json::Value &books = root["books"];
    for (uint32_t i = 0; i < books.size(); ++i)
    {
        Json::Value &book = books[i];
        std::cout << "book name: " << book["name"].asString() << ", price: " << book["price"].asFloat() << std::endl;
    }
    std::cout << "vip: " << root["vip"].asBool() << std::endl;

    if (!root["address"].isNull())
    {
        std::cout << "address: " << root["address"].asString() << std::endl;
    }
    else
    {
        std::cout << "address is null" << std::endl;
    }
}

bool JsoncppDecodeNew(const std::string &info)
{
    if (info.empty())
        return false;

    bool res;
    JSONCPP_STRING errs;
    Json::Value root;
    Json::CharReaderBuilder readerBuilder;
    std::unique_ptr<Json::CharReader> const jsonReader(readerBuilder.newCharReader());
    res = jsonReader->parse(info.c_str(), info.c_str() + info.length(), &root, &errs);
    if (!res || !errs.empty())
    {
        std::cout << "parseJson err. " << errs << std::endl;
        return false;
    }
    // printJsoncpp(root);

    return true;
}

bool JsoncppDecodeOld(const std::string &strJson)
{
    if (strJson.empty())
        return false;

    bool res;

    Json::Value root;
    Json::Reader jsonReader;

    res = jsonReader.parse(strJson, root);
    if (!res)
    {
        std::cout << "jsonReader.parse err. " << std::endl;
        return false;
    }

    // printJsoncpp(root);

    return true;
}

const char *strCjson = "{                 \\
	\\"name\\":	\\"milo\\",         \\
	\\"age\\":	80,                 \\
	\\"languages\\":	[\\"C++\\", \\"C\\"],\\
	\\"phone\\":	{                       \\
		\\"number\\":	\\"186****3143\\",    \\
		\\"type\\":	\\"home\\"            \\
	},                                  \\
	\\"books\\":	[{                         \\
			\\"name\\":	\\"Linux kernel development\\",   \\
			\\"price\\":	7.700000        \\
		}, {                            \\
			\\"name\\":	\\"Linux server development\\",   \\
			\\"price\\":	8               \\
		}],                             \\
	\\"vip\\":	true,                   \\
	\\"address\\":	null                \\
}                                      \\
";
#define TEST_COUNT 100000
int main()
{
    std::string jsonStrNew;
    std::string jsonStrOld;

    jsonStrNew = JsoncppEncodeNew();
    // JsoncppEncodeNew size: 337
    std::cout << "JsoncppEncodeNew size: " << jsonStrNew.size() << std::endl;
    std::cout << "JsoncppEncodeNew string: " << jsonStrNew << std::endl;
    JsoncppDecodeNew(jsonStrNew);

    jsonStrOld = JsoncppEncodeOld();
    // JsoncppEncodeOld size: 248
    std::cout << "\\n\\nJsoncppEncodeOld size: " << jsonStrOld.size() << std::endl;
    std::cout << "JsoncppEncodeOld string: " << jsonStrOld << std::endl;
    JsoncppDecodeOld(jsonStrOld);

    Json::Value root = JsoncppEncodeOldGet();
    Json::FastWriter writer;
    std::cout << "writer:\\n"  << std::endl;
    std::string jsonStr = writer.write(root);
    std::cout << "\\n\\njsonStr string: " << jsonStrOld << std::endl;
#if 1
    uint64_t startTime;
    uint64_t nowTime;
    
    startTime = getNowTime();
    std::cout << "jsoncpp encode time testing" << std::endl;
    for(int i = 0; i < TEST_COUNT; i++)
    {
        JsoncppEncodeNew();
    }
    nowTime = getNowTime();
    std::cout << "jsoncpp encode " << TEST_COUNT << " time, need time: "
         << nowTime-startTime << "ms"  << std::endl;

    startTime = getNowTime();
    std::cout << "\\njsoncpp encode time testing" << std::endl;
    for(int i = 0; i < TEST_COUNT; i++)
    {
        JsoncppEncodeOld();
    }
    nowTime = getNowTime();
    std::cout << "jsoncpp encode " << TEST_COUNT << " time, need time: "
         << nowTime-startTime << "ms"  << std::endl;

    startTime = getNowTime();
    std::cout << "\\njsoncpp decode time testing" << std::endl;
    for(int i = 0; i < TEST_COUNT; i++)
    {
        JsoncppDecodeNew(jsonStrNew);
    }
    nowTime = getNowTime();
    std::cout << "jsoncpp decode " << TEST_COUNT << " time, need time: "
         << nowTime-startTime << "ms"  << std::endl;

    startTime = getNowTime();
    std::cout << "\\njsoncpp decode time testing" << std::endl;
    for(int i = 0; i < TEST_COUNT; i++)
    {
        JsoncppDecodeOld(jsonStrNew);
    }
    nowTime = getNowTime();
    std::cout << "jsoncpp decode " << TEST_COUNT << " time, need time: "
         << nowTime-startTime << "ms"  << std::endl;
#endif

    return 0;
}
  • 编译运行如下:  
g++ jsoncpp_speed.cpp -o jsoncpp_speed -ljsoncpp -std=c++11

 

以上是关于Linux(程序设计):31---jsoncpp库(C++操作JSON)的主要内容,如果未能解决你的问题,请参考以下文章

请教关于linux中静态库与动态库的问题

linux 函数库使用

Linux共享库静态库动态库详解

Linux 查看依赖库

linux 下C标准库是动态库还是静态库,还是两种库都提供了?

Linux2.6 如何编写Makefile,使驱动程序能够编译链接静态库