使用 libjsoncpp 读取 JSON 字符串并转为对象
JsonCpp 是一个流行的 C++ JSON 解析库,下面介绍如何使用它来将 JSON 字符串转换为 C++ 对象。
基本使用步骤
1. 包含头文件
#include <json/json.h>
2. 创建 JSON 阅读器
Json::CharReaderBuilder readerBuilder;
Json::Value root;
JSONCPP_STRING errs;
3. 解析 JSON 字符串
const std::string jsonStr = R"(
{
"name": "John",
"age": 30,
"isStudent": false,
"courses": ["Math", "Science"],
"address": {
"street": "123 Main St",
"city": "New York"
}
}
)";
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
bool parsingSuccessful = reader->parse(jsonStr.c_str(),
jsonStr.c_str() + jsonStr.length(),
&root,
&errs);
if (!parsingSuccessful) {
std::cerr << "Failed to parse JSON: " << errs << std::endl;
return 1;
}
访问 JSON 数据
访问基本类型
std::string name = root["name"].asString();
int age = root["age"].asInt();
bool isStudent = root["isStudent"].asBool();
访问数组
const Json::Value& courses = root["courses"];
for (const auto& course : courses) {
std::cout << course.asString() << std::endl;
}
访问嵌套对象
std::string street = root["address"]["street"].asString();
std::string city = root["address"]["city"].asString();
完整示例代码
#include <iostream>
#include <string>
#include <json/json.h>
int main() {
// JSON 字符串
const std::string jsonStr = R"(
{
"name": "John",
"age": 30,
"isStudent": false,
"courses": ["Math", "Science"],
"address": {
"street": "123 Main St",
"city": "New York"
}
}
)";
// 解析 JSON
Json::CharReaderBuilder readerBuilder;
Json::Value root;
JSONCPP_STRING errs;
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
bool parsingSuccessful = reader->parse(jsonStr.c_str(),
jsonStr.c_str() + jsonStr.length(),
&root,
&errs);
if (!parsingSuccessful) {
std::cerr << "Failed to parse JSON: " << errs << std::endl;
return 1;
}
// 访问数据
std::string name = root["name"].asString();
int age = root["age"].asInt();
bool isStudent = root["isStudent"].asBool();
std::cout << "Name: " << name << std::endl;
std::cout << "Age: " << age << std::endl;
std::cout << "Is Student: " << (isStudent ? "Yes" : "No") << std::endl;
// 访问数组
std::cout << "\nCourses:" << std::endl;
const Json::Value& courses = root["courses"];
for (const auto& course : courses) {
std::cout << "- " << course.asString() << std::endl;
}
// 访问嵌套对象
std::cout << "\nAddress:" << std::endl;
std::string street = root["address"]["street"].asString();
std::string city = root["address"]["city"].asString();
std::cout << "Street: " << street << std::endl;
std::cout << "City: " << city << std::endl;
return 0;
}
编译与链接
编译时需要链接 jsoncpp 库:
g++ -std=c++11 your_file.cpp -ljsoncpp -o json_parser
错误处理
-
检查键是否存在:
if (root.isMember("name")) { // 键存在 }
-
类型检查:
if (root["age"].isInt()) { // 是整数类型 }
-
安全访问:
// 使用 get() 方法并提供默认值 int age = root.get("age", 0).asInt();
其他实用方法
将 Json::Value 转为字符串
Json::StreamWriterBuilder writerBuilder;
std::string jsonString = Json::writeString(writerBuilder, root);
修改 JSON 数据
root["age"] = 31; // 修改值
root["newKey"] = "newValue"; // 添加新键
JsonCpp 提供了简单直观的 API 来处理 JSON 数据,适合大多数 C++ 项目中的 JSON 处理需求。
使用 libjsoncpp 读取仅包含数组的 JSON 字符串
当 JSON 字符串只包含一个数组时,使用 libjsoncpp 解析的方法与解析普通 JSON 对象类似,但有一些特殊注意事项。
基本解析方法
示例 JSON 字符串
["apple", "banana", "orange", 42, true]
解析代码
#include <iostream>
#include <string>
#include <json/json.h>
int main() {
// JSON 数组字符串
const std::string jsonStr = R"(["apple", "banana", "orange", 42, true])";
// 解析 JSON
Json::CharReaderBuilder readerBuilder;
Json::Value root;
JSONCPP_STRING errs;
std::unique_ptr<Json::CharReader> reader(readerBuilder.newCharReader());
bool parsingSuccessful = reader->parse(jsonStr.c_str(),
jsonStr.c_str() + jsonStr.length(),
&root,
&errs);
if (!parsingSuccessful) {
std::cerr << "Failed to parse JSON: " << errs << std::endl;
return 1;
}
// 检查是否是数组
if (!root.isArray()) {
std::cerr << "The JSON is not an array!" << std::endl;
return 1;
}
// 遍历数组元素
std::cout << "Array elements:" << std::endl;
for (const auto& element : root) {
if (element.isString()) {
std::cout << "String: " << element.asString() << std::endl;
} else if (element.isInt()) {
std::cout << "Int: " << element.asInt() << std::endl;
} else if (element.isBool()) {
std::cout << "Bool: " << (element.asBool() ? "true" : "false") << std::endl;
}
// 可以添加其他类型的判断
}
return 0;
}
处理不同类型的数组元素
对象数组示例
[
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30}
]
解析代码
// 解析对象数组
for (const auto& item : root) {
if (item.isObject()) {
std::string name = item["name"].asString();
int age = item["age"].asInt();
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
}
实用技巧
-
检查数组大小:
int size = root.size(); std::cout << "Array size: " << size << std::endl;
-
直接访问元素:
// 访问第一个元素 if (!root.empty()) { Json::Value firstElement = root[0]; }
-
类型安全访问:
// 安全获取字符串元素 std::string fruit = root[0].isString() ? root[0].asString() : "default";
-
处理嵌套数组:
[[1, 2], [3, 4], [5, 6]]
for (const auto& innerArray : root) { for (const auto& number : innerArray) { std::cout << number.asInt() << " "; } std::cout << std::endl; }
错误处理增强版
try {
// 尝试获取元素
Json::Value element = root[10]; // 可能越界
if (element.isNull()) {
throw std::runtime_error("Element is null or out of bounds");
}
// 处理元素...
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
编译命令
g++ -std=c++11 json_array.cpp -ljsoncpp -o json_array_parser
通过以上方法,您可以灵活地处理各种只包含数组的 JSON 数据,无论是简单值数组、对象数组还是嵌套数组。