当前位置: 首页 > news >正文

JsonCpp: 一个好用且轻量级的JSON解析库

目录

1.简介

2.安装与集成

2.1.包管理器安装(推荐 Linux/macOS)

2.2.源码集成(适合所有系统)

3.核心组件与接口

4.基本使用示例

5.高级用法

6.注意事项

7.总结


1.简介

        JsonCpp 是一个功能完善的 C++ 库,用于解析、生成和操作 JSON(JavaScript Object Notation)数据。它遵循 JSON 标准,支持跨平台(Linux/macOS/Windows 等),且接口简洁,是 C++ 项目中处理 JSON 数据的常用选择。

        它的特点有:

1.功能完整:支持 JSON 所有基础类型(字符串、数字、布尔、数组、对象、null),以及嵌套结构。

2.双接口设计:提供 “简单接口”(快速解析 / 生成)和 “高级接口”(自定义配置,如格式化、错误处理)。

3.跨平台:纯 C++ 实现,不依赖系统特定库,兼容主流编译器(GCC、Clang、MSVC)。

4.轻量易集成:可通过源码(单头文件 / 多文件)或包管理器快速集成到项目。

5.支持注释:可配置解析含注释的 JSON(非标准 JSON 扩展,实用但需显式开启)。

2.安装与集成

JsonCpp 在 CMake 项目中的集成主要有两种方式,需根据项目需求选择:

集成方式适用场景优点缺点
1. 源码嵌入(Third-Party)需固定 JsonCpp 版本,避免依赖冲突版本可控,无需额外安装需手动配置 CMake 生成 config.h
2. 包管理器安装(vcpkg)追求便捷,项目依赖统一管理一键安装,CMake 自动查找版本依赖包管理器,需联网

2.1.包管理器安装(推荐 Linux/macOS)

Ubuntu/Debian

sudo apt-get install libjsoncpp-dev

macOS(Homebrew)

brew install jsoncpp

Windows(vcpkg)

若项目使用 vcpkg 管理依赖(如你之前用 vcpkg 安装 asio、openssl),可一键安装 JsonCpp 并通过 CMake 自动查找,无需手动处理源码和 config.h

步骤 1:用 vcpkg 安装 JsonCpp

打开 vcpkg 命令行,执行:

# 安装 JsonCpp(x64-windows 对应 64位,根据你的架构调整)
vcpkg install jsoncpp:x64-windows

步骤 2:CMake 配置(极简!)

在项目 CMakeLists.txt 中通过 find_package 自动查找 JsonCpp,无需手动处理源码:

cmake_minimum_required(VERSION 3.10)
project(JsonCppDemo)
set(CMAKE_CXX_STANDARD 11)# -------------------------- 关键:通过 vcpkg 查找 JsonCpp --------------------------
# 需确保 CMake 能找到 vcpkg 的包(通过 -DCMAKE_TOOLCHAIN_FILE 指定 vcpkg 工具链)
find_package(jsoncpp CONFIG REQUIRED)# -------------------------- 编译项目 --------------------------
add_executable(JsonCppDemo src/main.cpp)# -------------------------- 链接 JsonCpp 库 --------------------------
target_link_libraries(JsonCppDemo PRIVATE jsoncpp_lib)  # 链接 JsonCpp 库

步骤 3:CMake 命令行指定 vcpkg 工具链

运行 CMake 时,需通过 -DCMAKE_TOOLCHAIN_FILE 告诉 CMake vcpkg 的工具链路径(否则找不到 JsonCpp):

# 替换为你的 vcpkg 工具链路径(通常是 vcpkg 安装目录下的 scripts/buildsystems/vcpkg.cmake)
cmake .. -G "Ninja" -DCMAKE_TOOLCHAIN_FILE="C:/Users/Administrator/vcpkg/scripts/buildsystems/vcpkg.cmake" -A x64

2.2.源码集成(适合所有系统)

适合将 JsonCpp 源码放在项目 third_party/Json 目录下(如你之前的 third_party/Json 路径),需手动配置 CMake 生成关键文件(如 config.h)。

步骤 1:准备 JsonCpp 源码

1.从 JsonCpp 官方仓库 下载源码(推荐 1.9.x 稳定版);

2.解压后将核心目录 src/lib_json 和头文件目录 include/json 复制到项目的 third_party/Json 下,最终目录结构如下:

你的项目根目录/
├── third_party/
│   └── Json/
│       ├── include/          # JsonCpp 头文件目录
│       │   └── json/
│       │       ├── json.h    # 核心头文件
│       │       └── reader.h  # 解析相关头文件
│       └── src/
│           └── lib_json/     # JsonCpp 核心源码
│               ├── json_reader.cpp  # 解析实现
│               ├── json_value.cpp   # 数据结构实现
│               ├── json_writer.cpp  # 生成实现
│               ├── config.h.in      # 配置文件模板(关键!)
│               └── assertions.h     # 内部断言头文件
├── src/                      # 你的项目源码
│   └── main.cpp
└── CMakeLists.txt            # 项目CMake配置

步骤 2:CMake 配置(核心!)

在项目根目录的 CMakeLists.txt 中添加 JsonCpp 的编译配置,重点解决 config.h 生成 和 头文件 / 源码路径关联

# -------------------------- 1. 基础配置:指定C++标准 --------------------------
cmake_minimum_required(VERSION 3.10)
project(JsonCppDemo)
set(CMAKE_CXX_STANDARD 11)  # JsonCpp 1.9.x 支持 C++11+
set(CMAKE_CXX_STANDARD_REQUIRED ON)# -------------------------- 2. 配置 JsonCpp 路径 --------------------------
# 设定 JsonCpp 源码根目录(根据你的实际路径调整)
set(JSONCPP_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/third_party/Json)
# JsonCpp 头文件目录(include/json)
set(JSONCPP_INCLUDE_DIR ${JSONCPP_ROOT}/include)
# JsonCpp 核心源码文件(src/lib_json下的.cpp)
set(JSONCPP_SOURCES${JSONCPP_ROOT}/src/lib_json/json_reader.cpp${JSONCPP_ROOT}/src/lib_json/json_value.cpp${JSONCPP_ROOT}/src/lib_json/json_writer.cpp
)# -------------------------- 3. 生成 JsonCpp 关键配置文件 config.h --------------------------
# JsonCpp 的 config.h 由 config.h.in 模板生成(替换 @XXX@ 宏,如版本、平台)
set(JSONCPP_CONFIG_IN ${JSONCPP_ROOT}/src/lib_json/config.h.in)  # 模板路径
set(JSONCPP_CONFIG_OUT ${CMAKE_CURRENT_BINARY_DIR}/jsoncpp_config.h)  # 生成路径(放build目录)
configure_file(${JSONCPP_CONFIG_IN}${JSONCPP_CONFIG_OUT}@ONLY  # 仅替换 @XXX@ 格式的宏,避免冲突
)# -------------------------- 4. 关联头文件目录 --------------------------
# ① 添加 JsonCpp 公开头文件目录(include/json)
include_directories(${JSONCPP_INCLUDE_DIR})
# ② 添加生成的 config.h 目录(build目录,解决 "config.h 找不到" 问题)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
# ③ 添加 JsonCpp 内部头文件目录(src/lib_json,解决 "assertions.h 找不到" 问题)
include_directories(${JSONCPP_ROOT}/src/lib_json)# -------------------------- 5. 编译项目:关联源码和 JsonCpp --------------------------
# 你的项目源码(如 main.cpp)
add_executable(JsonCppDemosrc/main.cpp${JSONCPP_SOURCES}  # 加入 JsonCpp 核心源码
)

步骤 3:修正 JsonCpp 内部头文件引用(关键!)

JsonCpp 源码中默认包含 #include "config.h",但我们生成的配置文件是 jsoncpp_config.h(避免与其他库的 config.h 冲突),需手动修改源码中的引用:

1.打开 third_party/Json/src/lib_json/json_tool.h,将第 10 行(或包含 config.h 的行):

#include "config.h"

替换为:

#include "jsoncpp_config.h"

2.若其他文件(如 json_reader.cpp)也包含 config.h,同样替换为 jsoncpp_config.h

3.核心组件与接口

JsonCpp 的核心功能围绕 3 个关键类展开,以及新旧两套接口(推荐使用新接口):

1.核心数据类型:Json::Value

Json::Value 是 JsonCpp 中最基础的类,用于存储任意 JSON 数据(类似 “万能容器”),支持所有 JSON 类型:

  • 基础类型:nullboolintdoublestd::string
  • 复合类型:array(数组,类似 std::vector)、object(对象,类似 std::map)。

常用方法

// 创建不同类型的Value
Json::Value null_val;                     // 默认是null
Json::Value bool_val(true);               // 布尔值
Json::Value int_val(123);                 // 整数
Json::Value str_val("hello");             // 字符串
Json::Value arr_val; arr_val.append(456); // 数组(添加元素)
Json::Value obj_val; obj_val["key"] = "val"; // 对象(键值对)// 类型判断
bool is_null = null_val.isNull();
bool is_obj = obj_val.isObject();
bool is_arr = arr_val.isArray();// 类型转换(需确保类型匹配,否则返回默认值)
int num = int_val.asInt();          // 转为int
std::string str = str_val.asString(); // 转为string

2.解析 JSON:Json::CharReader(新接口,推荐)

用于将 JSON 字符串或文件解析为 Json::Value 对象,替代旧版 Json::Reader(已废弃)。需配合 Json::CharReaderBuilder 使用。

解析流程

  1. 创建 CharReaderBuilder(配置解析选项,如是否允许注释)。
  2. 获取 CharReader 实例(解析器)。
  3. 调用 parse() 方法解析 JSON 字符串 / 文件,结果存入 Json::Value
  4. 检查解析错误(通过输出参数获取错误信息)。

3.生成 JSON:Json::StreamWriter(新接口,推荐)

用于将 Json::Value 对象转换为 JSON 字符串,替代旧版 Json::Writer(已废弃)。需配合 Json::StreamWriterBuilder 使用,支持自定义格式化(缩进、换行等)。

4.基本使用示例

示例 1:解析 JSON 字符串并读取数据

#include <iostream>
#include <string>
#include "json/json.h"int main() {// 待解析的JSON字符串std::string json_str = R"({"name": "JsonCpp","version": 1.9,"is_stable": true,"features": ["parse", "generate", "modify"],"author": {"name": "open-source","email": "none@example.com"}})";// 1. 配置解析器Json::CharReaderBuilder builder;Json::CharReader* reader = builder.newCharReader();// 2. 解析JSON字符串Json::Value root;std::string errors; // 存储解析错误信息bool parse_success = reader->parse(json_str.data(), json_str.data() + json_str.size(), &root, &errors);delete reader; // 释放解析器// 3. 检查解析结果if (!parse_success) {std::cerr << "解析失败:" << errors << std::endl;return 1;}// 4. 读取JSON数据(需确保键存在且类型匹配)std::string name = root["name"].asString();          // "JsonCpp"double version = root["version"].asDouble();         // 1.9bool is_stable = root["is_stable"].asBool();         // truestd::string feature0 = root["features"][0].asString(); // "parse"std::string author_name = root["author"]["name"].asString(); // "open-source"// 输出结果std::cout << "名称:" << name << "\n"<< "版本:" << version << "\n"<< "是否稳定:" << std::boolalpha << is_stable << "\n"<< "第一个特性:" << feature0 << "\n"<< "作者:" << author_name << std::endl;return 0;
}

示例 2:构建 JSON 数据并生成字符串

#include <iostream>
#include <string>
#include "json/json.h"int main() {// 1. 构建JSON数据Json::Value root;// 添加基本类型root["status"] = "success";root["code"] = 200;root["data"]["id"] = 1001;root["data"]["name"] = "test";root["data"]["scores"] = Json::Value(Json::arrayValue); // 初始化数组root["data"]["scores"].append(90.5);root["data"]["scores"].append(88);root["data"]["is_passed"] = true;// 2. 配置生成器(自定义格式化)Json::StreamWriterBuilder builder;builder["indentation"] = "  "; // 缩进为2个空格(默认4个)std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());// 3. 生成JSON字符串(写入到字符串流)std::stringstream ss;writer->write(root, &ss);std::string json_str = ss.str();// 输出结果std::cout << "生成的JSON:\n" << json_str << std::endl;return 0;
}

输出结果(格式化后的 JSON):

{"code": 200,"data": {"id": 1001,"is_passed": true,"name": "test","scores": [90.5,88]},"status": "success"
}

示例 3:修改与删除 JSON 数据

#include <iostream>
#include "json/json.h"int main() {// 初始化一个JSON对象Json::Value obj;obj["a"] = 1;obj["b"] = "original";obj["c"] = Json::Value(Json::arrayValue);obj["c"].append(10);obj["c"].append(20);// 1. 修改数据obj["a"] = 2; // 修改已有键的值obj["b"] = "modified";obj["c"][0] = 100; // 修改数组元素// 2. 添加新键值对obj["d"] = false;// 3. 删除键(使用removeMember)obj.removeMember("a");// 输出修改后的结果Json::StreamWriterBuilder builder;std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());writer->write(obj, &std::cout);// 输出:{"b":"modified","c":[100,20],"d":false}return 0;
}

5.高级用法

1.解析含注释的 JSON(非标准扩展)

默认情况下,JSON 标准不支持注释,但 JsonCpp 可通过配置允许解析 // 或 /* */ 注释:

Json::CharReaderBuilder builder;
// 允许注释(需包含json/features.h)
builder.settings_["allowComments"] = true; 
// 允许单引号(非标准,可选)
builder.settings_["allowSingleQuotes"] = true; 

2.处理大型 JSON 文件(避免内存占用过高)

对于大型 JSON 文件,可通过流式解析(逐行读取)减少内存占用:

std::ifstream ifs("large.json");
Json::CharReaderBuilder builder;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value root;
std::string errors;// 从文件流解析(而非一次性读入字符串)
bool success = reader->parse(std::istreambuf_iterator<char>(ifs), std::istreambuf_iterator<char>(), &root, &errors
);

3.自定义 JSON 生成格式

通过 StreamWriterBuilder 的配置项自定义输出格式:

Json::StreamWriterBuilder builder;
builder["indentation"] = "\t"; // 用制表符缩进
builder["enableYAMLCompatibility"] = true; // 兼容YAML格式(无尾逗号)
builder["precision"] = 6; // 浮点数精度(保留6位小数)

6.注意事项

1.类型安全Json::Value 的 asInt()asString() 等方法在类型不匹配时会返回默认值(如 0、空字符串),建议先通过 isInt()isString() 等方法检查类型。

2.键存在性:访问 root["key"] 时,若键不存在会返回 null,建议用 root.isMember("key") 检查键是否存在。

3.线程安全Json::Value 及解析 / 生成器均不保证线程安全,多线程操作需加锁(如 std::mutex)。

4.版本兼容性:旧接口(Json::ReaderJson::StyledWriter)已被标记为废弃,新项目建议使用 CharReaderBuilder 和 StreamWriterBuilder

5.内存管理Json::Value 内部管理内存,赋值时会自动拷贝数据(大对象拷贝成本高,可考虑移动语义 std::move)。

6.出现:config.h: No such file or directory,那是因为未生成 config.h(源码嵌入方式),或生成路径未加入包含目录。参考2.2,通过 configure_file 生成 jsoncpp_config.h,并添加 include_directories(${CMAKE_CURRENT_BINARY_DIR})

7.总结

        JsonCpp 是 C++ 中处理 JSON 的成熟方案,通过 Json::Value 存储数据,CharReader 解析,StreamWriter 生成,接口直观且功能全面。适合各类场景(配置文件解析、API 数据交互、日志格式化等),掌握其核心类和基本流程后,可轻松应对复杂 JSON 操作。


文章转载自:

http://xsRD0hFI.fncgw.cn
http://7QfyB1EK.fncgw.cn
http://1YYfsr5O.fncgw.cn
http://eDMsT3c5.fncgw.cn
http://qvZsPXQP.fncgw.cn
http://SYZMd7z8.fncgw.cn
http://4ff55RLH.fncgw.cn
http://m0OTvq8s.fncgw.cn
http://uMTYWiBA.fncgw.cn
http://aF9FJMbN.fncgw.cn
http://mbSQ4nYE.fncgw.cn
http://6HVZqPwh.fncgw.cn
http://qS4IdNvx.fncgw.cn
http://o0hWDMbW.fncgw.cn
http://rRx8hApt.fncgw.cn
http://Jx5rAJve.fncgw.cn
http://X8OyJ7go.fncgw.cn
http://Uqp83yRh.fncgw.cn
http://g0YAllpL.fncgw.cn
http://JpYBQD8i.fncgw.cn
http://wl8mRXMs.fncgw.cn
http://S600i9Id.fncgw.cn
http://IRagSY4v.fncgw.cn
http://SCh3pRqx.fncgw.cn
http://H8dBo274.fncgw.cn
http://jpmQScD1.fncgw.cn
http://QypX1O8a.fncgw.cn
http://XM3ZqI3o.fncgw.cn
http://YNlJquqU.fncgw.cn
http://y5ZcjReH.fncgw.cn
http://www.dtcms.com/a/387511.html

相关文章:

  • 【设计模式】桥接模式
  • ACP(五):优化提示词(Prompt),精细地控制大模型的输出
  • Egg.js 性能测试全解析:从压力测试到深度调优
  • 自制脚本,解决Ubuntu20.04 键盘会突然失灵、键盘延迟突然很大问题
  • 172.在vue3中使用openlayers:引用 hover 效果,展示各种鼠标 cursor 样式
  • SpringBoot Oracle
  • LLMs之IR:《MUVERA: Multi-Vector Retrieval via Fixed Dimensional Encodings》的翻译与解读
  • Redis与Java集成实战:从入门到高级应用
  • Chromium 138 编译指南 macOS篇:配置depot_tools(三)
  • qt QHXYModelMapper详解
  • 机器学习中的编码问题和标准化:类别编码、one-hot编码缺陷及改进
  • Qt QHorizontalStackedBarSeries详解
  • Python爬虫实战:研究Pandas,构建全运会数据采集和分析系统
  • 告别冗余 DOM:Vue Fragment 用法与性能优化解析
  • 快速排序:原理、实现与优化
  • JavaScript性能优化实战:深入剖析性能瓶颈与最佳实践
  • Lattice ECP5系列FPGA介绍
  • PySpark 窗口函数row_number、lag、lead的使用简述
  • 华为FreeBuds 7i不同设备要如何连接?
  • 使用LVS架设服务器集群系统实现负载均衡与高可用的知识点详解
  • 84-dify案例分享-使用Qwen-Image实现文生图、图生图
  • 留个档,Unity,Animation控制相机,出现抖动的问题记录
  • CentOS 8.5部署Zabbix6.0 server端
  • CentOS系统下安装Docker记录
  • CentOS 7 如何安装 EPEL 源?epel-release-latest-7.noarch.rpm 安装教程(附安装保存)
  • CentOS 7 源码版 PhpMyAdmin 安装指南(适配 Nginx+PHP-FPM 环境)
  • 在 WSL Ubuntu 上使用 Docker 搭建可被 Ansible 控制的受控节点环境
  • 数据赋能,安全护航——D-QS工程造价数字化平台的数据治理与行业应用
  • Matplotlib 可视化:从基础绘图到高级定制
  • 知识管理与高效学习技术