【视频点播系统】JsonCpp 介绍及使用
·
JsonCpp 介绍及使用
一. Json 简介
JSON (JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于 JavaScript 的一个子集,但尽管它来源于 JavaScript,但 JSON 是独立于语言的,可以被多种编程语言读取。以下是关于 JSON 的一些关键点:
1. 基本结构
- 对象:由键值对组成,大括号 {} 包围。
- 数组:由值的有序集合组成,方括号 [] 包围。
- 值:可以是字符串、数字、对象、数组、布尔值 (true / false) 或 null
2 语法规则
- 键值对以 “key”: value 的形式出现,键和值之间用冒号分隔
- 多个键值对之间用逗号分隔。
- 所有键都必须是字符串,并且用双引号包围。
3. 示例
{
"name": "John Doe",
"age": 30,
"is_student": false,
"skills": ["JavaScript", "Python", "C++"],
"address": {
"street": "123 Main St",
"city": "Anytown",
"state": "CA"
}
}
4. 用途
- 数据存储:作为一种数据格式,用于文件和数据库存储。
- 数据交换:作为 APIs 和网络请求中数据交换的标准格式。
- 配置文件:用于应用程序的配置信息。
二. JsonCpp 简介
1. 安装
sudo apt install libjsoncpp-dev
由于在环境搭建中已经安装了 JsonCpp,这里不需要再次安装了。
2. 简介
JsonCpp 是一个高性能的 JSON 库,用于处理 JSON 数据。它提供了完整的 JSON 标准支持,包括解析 JSON 字符串、生成 JSON 字符串、读写 JSON 对象和数组等功能。
3. 特点
- 易于使用:JsonCpp 提供了简单直观的 API,使得在 C++ 程序中处理 JSON 数据变得容易。
- 高性能:它被设计为高性能,可以快速解析和生成大量 JSON 数据。
- 跨平台:支持多种操作系统,包括 Windows、Linux 和 macOS。
- 无依赖:JsonCpp 不依赖于任何外部库,可以轻松集成到任何 C++ 项目中。
- 完全支持 C++11:利用 C++11 的特性,如智能指针和正则表达式。
4. 使用
4.1 头文件和链接库

#include <jsoncpp/json/json.h>
程序编译时库的链接
-ljsoncpp
4.2 数据转储
namespace Json {
enum ValueType {
nullValue = 0, ///< 'null' value
intValue, ///< signed integer value
uintValue, ///< unsigned integer value
realValue, ///< double value
stringValue, ///< UTF-8 string value
booleanValue, ///< bool value
arrayValue, ///< array value (ordered list)
objectValue ///< object value (collection of name/value pairs).
};
class JSON_API Value {
public:
void swap(Value& other);
void copy(const Value& other);
// 获取数据接口
const char* asCString() const;
String asString() const;
Int asInt() const;
UInt asUInt() const;
Int64 asInt64() const;
UInt64 asUInt64() const;
float asFloat() const;
double asDouble() const;
bool asBool() const;
// 判断数据类型
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;
// Array-API
ArrayIndex size() const;
bool empty() const;
void clear();
void resize(ArrayIndex newSize);
Value& operator[](ArrayIndex index);
Value& append(const Value& value);
Value& operator[](const char* key);
Value& operator[](const String& key);
void removeMember(const String& key);
bool isMember(const String& key) const;
String toStyledString() const;
}
}
4.3 序列化
namespace Json {
class JSON_API StreamWriter {
public:
virtual int write(Value const& root, OStream* sout) = 0;
class JSON_API Factory {
public:
virtual StreamWriter* newStreamWriter() = 0;
}
};
class streamWriterBuilder : public StreamWriter::Factory {
public:
Json::Value settings_;
StreamWriter* newStreamWriter() const override;
};
}
4.4 反序列化
namespace Json {
class JSON_API CharReader {
public:
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root, String* errs) = 0;
class JSON_API Factory {
public:
virtual CharReader* newCharReader() const = 0;
}
};
class JSON_API CharReaderBuilder : public CharReader::Factory {
public:
Json::Value settings_;
CharReader* newCharReader() const override;
};
}
三. JsonCpp 使用样例
1. 目录结构
jsoncpp/
|-- main.cc
|-- makefile
|-- serialize.cc
|-- unserialize.cc
2. 项目构建
# makefile
all: main serialize unserialize
main: main.cc
g++ -o $@ $^ -std=c++17 -ljsoncpp
serialize: serialize.cc
g++ -o $@ $^ -std=c++17 -ljsoncpp
unserialize: unserialize.cc
g++ -o $@ $^ -std=c++17 -ljsoncpp
.PHONY: clean
clean:
rm -f main serialize unserialize
3 样例代码
3.1 序列化
简单的序列化:
// main.cc
#include <iostream>
#include <jsoncpp/json/json.h>
int main(int argc, char* argv[])
{
Json::Value val;
val["name"] = "zhangsan";
val["age"] = 18;
val["score"].append(95.5);
val["score"].append(90.5);
val["score"].append(85.5);
std::string str = val.toStyledString();
std::cout << str << std::endl;
return 0;
}

标准的序列化:
// serialize.cc
#include <iostream>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main(int argc, char* argv[])
{
Json::Value val;
val["name"] = "zhangsan";
val["age"] = 18;
val["score"].append(95.5);
val["score"].append(90.5);
val["score"].append(85.5);
// 1.实例化建造者对象
Json::StreamWriterBuilder builder;
builder["indentation"] = ""; // 关闭缩进
// 2.通过建造者对象实例化序列化对象
std::unique_ptr<Json::StreamWriter> sw(builder.newStreamWriter());
// 3.通过序列化对象进行序列化
std::stringstream ss;
int ret = sw->write(val, &ss);
if (ret != 0) {
std::cout << "write failed" << std::endl;
return -1;
}
// 4.获取序列化后的字符串
std::string str = ss.str();
std::cout << str << std::endl;
return 0;
}

3.2 反序列化
标准的反序列化:
// unserialize.cc
#include <iostream>
#include <sstream>
#include <memory>
#include <jsoncpp/json/json.h>
int main(int argc, char* argv[])
{
// 去除所有字符的特殊含义
std::string str = R"({"age":18,"name":"zhangsan","score":[95.5,90.5,85.5]})";
// 1.实例化建造者对象
Json::CharReaderBuilder builder;
// 2.通过建造者对象实例化反序列化对象
std::unique_ptr<Json::CharReader> cr(builder.newCharReader());
// 3.通过反序列化对象进行反序列化
Json::Value val;
std::string errors;
bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &val, &errors);
if (!ret) {
std::cout << "parse failed: " << errors << std::endl;
return -1;
}
// 4.获取反序列化后的Json::Value对象
std::cout << "name: " << val["name"].asString() << std::endl;
std::cout << "age: " << val["age"].asInt() << std::endl;
std::cout << "score: ";
if (!val["score"].isNull() && val["score"].isArray()) {
int size = val["score"].size();
for (int i = 0; i < size; ++i) {
std::cout << val["score"][i].asFloat() << " ";
}
}
std::cout << std::endl;
return 0;
}

四. JsonCpp 封装

将 example 文件夹改名为 test,并创建一个新的 example 文件夹并且将 gflags、gtest、spdlog 和 jsoncpp 移动到 example 文件夹下。


1. 设计与实现
- 原因:为了能够在项目中使序列化和反序列化更加便捷。
- 设计:封装一个 Json 工具类,内部包含两个接口,序列化和反序列化接口。
- 序列化:输入 Json::Value 对象;输出 Json 格式的字符串。
- 反序列化:输入 Json 格式的字符串;输入 Json::Value 对象。
// xzyutil.h
#pragma once
#include <iostream>
#include <sstream>
#include <memory>
#include <optional>
#include <jsoncpp/json/json.h>
namespace xzyutil {
class JSON {
public:
// 序列化
static std::optional<std::string> serialize(const Json::Value& value);
// 反序列化
static std::optional<Json::Value> unserialize(const std::string& str);
};
}
// xzyutil.cc
#include "xzyutil.h"
namespace xzyutil {
// 序列化
std::optional<std::string> JSON::serialize(const Json::Value& val) {
// 1.实例化建造者对象
Json::StreamWriterBuilder builder;
builder["indentation"] = "";
// 2.通过建造者对象实例化序列化对象
std::unique_ptr<Json::StreamWriter> sw(builder.newStreamWriter());
// 3.通过序列化对象进行序列化
std::stringstream ss;
int ret = sw->write(val, &ss);
if (ret != 0) {
std::cout << "序列化失败!" << std::endl;
return std::optional<std::string>();
}
// 4.获取序列化后的字符串
return ss.str();
}
// 反序列化
std::optional<Json::Value> JSON::unserialize(const std::string& str) {
// 1.实例化建造者对象
Json::CharReaderBuilder builder;
// 2.通过建造者对象实例化反序列化对象
std::unique_ptr<Json::CharReader> cr(builder.newCharReader());
// 3.通过反序列化对象进行反序列化
Json::Value val;
std::string errors;
bool ret = cr->parse(str.c_str(), str.c_str() + str.size(), &val, &errors);
if (!ret) {
std::cout << "反序列化失败!" << std::endl;
return std::optional<Json::Value>();
}
// 4.获取反序列化后的Json::Value对象
return val;
}
}
2. 使用
2.1 目录结构
|-- source
| |-- xzyutil.cc
| |-- xzyutil.h
|-- test
|-- jsoncpp
| |-- json_test
| |-- json_test.cc
| |-- makefile
2.2 项目构建
# makefile
json_test: json_test.cc ../../source/xzyutil.cc
g++ -o $@ $^ -std=c++17 -ljsoncpp
.PHONY: clean
clean:
rm -f json_test
2.3 代码编写
// json_test.cc
#include "../../source/xzyutil.h"
void serialize_test()
{
Json::Value val;
val["name"] = "zhangsan";
val["age"] = 18;
val["score"].append(95.5);
val["score"].append(90.5);
val["score"].append(85.5);
std::optional<std::string> str = xzyutil::JSON::serialize(val);
if (!str.has_value()) {
std::cout << "序列化失败!" << std::endl;
return;
}
std::cout << str.value() << std::endl;
}
void unserialize_test()
{
std::string str = R"({"name":"zhangsan","age":18,"score":[95.5,90.5,85.5]})";
std::optional<Json::Value> val = xzyutil::JSON::unserialize(str);
if (!val.has_value()) {
std::cout << "反序列化失败!" << std::endl;
return;
}
std::cout << "name: " << val.value()["name"].asString() << std::endl;
std::cout << "age: " << val.value()["age"].asInt() << std::endl;
std::cout << "score: ";
if (!val.value()["score"].isNull() && val.value()["score"].isArray()) {
int size = val.value()["score"].size();
for (int i = 0; i < size; ++i) {
std::cout << val.value()["score"][i].asFloat() << " ";
}
}
std::cout << std::endl;
}
int main(int argc, char* argv[])
{
serialize_test();
unserialize_test();
return 0;
}

提交本地代码到远程仓库

火山引擎视频云技术社区,是面向 AI 音视频开发者的技术交流平台。这里汇聚源自抖音、豆包等亿级 DAU 产品的 RTC、直播、点播、AI 媒体处理、音视频互动技术,提供接入指南、最佳实践、性能调优、场景案例、Demo 代码、开源项目、白皮书和 API 文档。社区汇聚官方工程师与一线开发者,为 AI 视频通话、数字人、AI 视频处理等应用的开发与落地提供技术支持。
更多推荐
所有评论(0)