JSONCPP 使用指南:在 C++ 中高效处理 JSON 数据
json广泛应用于 前后端通信、微服务间数据传输,所以熟悉json的格式和使用尤为重要
📦 目录
1️⃣ 简介
JsonCpp 是一个开源的 C++ 库(MIT License),提供:
- 完整的 JSON 解析/序列化功能
- DOM 风格接口
- SAX 风格解析器(0.y.z 版本后)
- 支持注释保留
- 精确的浮点数处理
GitHub仓库:open-source-parsers/jsoncpp
2️⃣ 安装与配置
Linux (Ubuntu/Debian)
bash
sudo apt-get install libjsoncpp-dev
macOS (Homebrew)
bash
brew install jsoncpp
Windows (vcpkg)
powershell
vcpkg install jsoncpp
CMake集成示例
可以参考这篇文章使用qt的方式编译
链接: libevent的编译
cmake
find_package(JsonCpp REQUIRED)
target_link_libraries(YourTarget PRIVATE JsonCpp::JsonCpp)
3️⃣ 核心用法
🔍 读取与解析 JSON
从字符串解析
cpp
#include <json/json.h>
std::string jsonStr = R"({"name":"Alice","age":25,"scores":[90,85,95]})";
Json::Value root;
JSONCPP_STRING err;
Json::CharReaderBuilder builder;
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
if (!reader->parse(jsonStr.c_str(), jsonStr.c_str() + jsonStr.size(), &root, &err)) {
std::cerr << "Parse error: " << err << std::endl;
return -1;
}
// 访问数据示例
std::cout << "Name: " << root["name"].asString() << std::endl; // Alice
从文件读取(推荐方式)
cpp
Json::Value root;
std::ifstream configFile("config.json");
configFile >> root; // 自动解析文件内容
🛠️ 构建与输出 JSON
构建JSON对象
cpp
Json::Value data;
data["name"] = "Bob";
data["age"] = 30;
// 添加数组元素(两种方式)
data["hobbies"].append("reading");
data["hobbies"][1] = "swimming";
// 添加嵌套对象
data["address"]["city"] = "New York";
data["address"]["zip"] = "10001";
JSON序列化输出(格式化)
cpp
Json::StreamWriterBuilder writerBuilder;
writerBuilder["indentation"] = "\t"; // 设置缩进格式
const std::string output = Json::writeString(writerBuilder, data);
std::cout << output << std::endl;
/* Output:
{
"address" : {
"city" : "New York",
"zip" : "10001"
},
"age" : 30,
"hobbies" : [
"reading",
"swimming"
],
"name" : "Bob"
}
*/
🔧 类型操作
Method | Description |
---|---|
isNull() |
Check if value is null |
isArray() |
Check if value is array |
isObject() |
Check if value is object |
isNumeric() |
Check if numeric type |
asInt() |
Convert to int |
asFloat() |
Convert to float |
asString() |
Convert to string |
示例:
cpp
if (root.isMember("age") && root["age"].isInt()) {
int age = root["age"].asInt();
}
else {
// Handle missing or invalid field...
}
4️⃣ 错误处理最佳实践
Case1:异常捕获(启用 exceptions)
编译时需定义 JSON_USE_EXCEPTION=1
cpp
try {
Json::Value root;
std::cin >> root; // Invalid input will throw exception
} catch (const Json::Exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
Case2:空指针检测(禁用 exceptions)
cpp
Json::CharReaderBuilder builder;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
if (!reader) {
// Handle allocation failure...
}
5️⃣ 🔝高级功能
✨保留注释(0.y.z+版本)
cpp
Json::Value withComments;
Json::Reader reader;
reader.parse("{/* comment */}", withComments);
// Write with comments preserved...
🌐宽松模式解析(允许非常规格式)
cpp
Json::CharReaderBuilder builder;
builder.settings_["allowComments"] = true;
builder.settings_["strictRoot"] = false;
🎨自定义写入器(扩展输出格式)
继承 Json::StreamWriter
:
cpp
class CustomWriter : public Json::StreamWriter {
protected:
void writeValue(const Json::Value& value) override {
// Custom implementation...
}
};
6️⃣ ⚠️注意事项
-
跨平台差异
Windows下注意字符编码问题(建议统一使用UTF-8)
-
性能优化
- SAX接口比DOM更节省内存
- Reuse
CharReader
/StreamWriter
instances when possible
-
内存管理
cpp// Good practice: Json::Value* createData() { return new Json::Value(); // Manual management needed! } // Better use smart pointers: auto data = std::make_unique<Json::Value>();
-
版本兼容性
v1.y.z vs v0.y.z API有差异需注意
🎯总结
通过本文您已掌握:
✅ JSONCPP的基本使用方法
✅ JSON数据的高效处理技巧
✅常见问题的解决方案
官方文档参考:JSONCPP Documentation
在实际项目中推荐结合CMake进行依赖管理并编写完善的单元测试!