Qt中解析JSON文件
在Qt中解析JSON字符串主要有两种方式:使用QJsonDocument
类或使用QJsonDocument
结合QVariant
。以下是详细的解析方法:
使用QJsonDocument(推荐)
这种方式的主要相关类如下:
QJsonDocument: QJsonDocument
是 Qt 中处理 JSON 数据的核心类,它提供了在内存中读写 JSON 文档的功能。
主要功能
- 解析 JSON:从 UTF-8 编码的文本创建 JSON 文档
- 生成 JSON:将内存中的 JSON 数据转换为字符串或二进制格式
- 数据访问:提供对 JSON 对象和数组的访问接口
- 格式转换:支持紧凑和缩进两种输出格式
QJsonObject:QJsonObject
是 Qt 中用于表示 JSON 对象的类,它存储键值对集合,其中键是字符串,值可以是各种 JSON 类型。
主要特性
- 键值对存储:存储
QString
作为键,QJsonValue
作为值 - 无序集合:键的顺序不保证与插入顺序一致
- 隐式共享:使用写时复制技术,拷贝开销小
- 类型安全:提供多种类型检查和转换方法
QJsonValue:
QJsonValue
是 Qt 中表示 JSON 值的类,它可以存储 JSON 标准支持的所有数据类型。它是 Qt JSON 系统的核心基础类。
主要特性
- 多类型存储:可以存储 JSON 支持的所有数据类型
- 值语义:拷贝和赋值操作是高效的(隐式共享)
- 类型安全:提供严格的类型检查和转换方法
- 空值和未定义值:支持 JSON null 和未定义值
支持的数据类型
QJsonValue
可以存储以下类型的值:
类型 | 描述 | 对应的 Qt 类型 |
---|---|---|
Null |
JSON null 值 | QJsonValue::Null |
Bool |
布尔值 | bool |
Double |
双精度浮点数 | double |
String |
字符串 | QString |
Array |
JSON 数组 | QJsonArray |
Object |
JSON 对象 | QJsonObject |
Undefined |
未定义值(无效值) | QJsonValue::Undefined |
QJsonArray:
QJsonArray
是 Qt 中用于表示 JSON 数组的类,它存储有序的 QJsonValue
集合。JSON 数组是值的有序列表,可以包含不同类型的元素。
主要特性
- 有序集合:元素保持插入顺序
- 混合类型:可以存储不同类型的值
- 隐式共享:使用写时复制技术,拷贝开销小
- 动态大小:支持动态添加和删除元素
- 索引访问:支持通过索引随机访问元素
下面我们就用进行简单的实战解析。
一、解析简单Json对象
#include <QCoreApplication>
#include<QJsonDocument>
#include<QJsonObject>
#include<QJsonValue>
#include<QJsonArray>
void PraseJson()
{
QString strJson = R"({
"name":"张三",
"age":30,
"isStudent":false
})";
QJsonDocument doc = QJsonDocument::fromJson(strJson.toUtf8());
if(doc.isNull() || !doc.isObject())
{
qDebug() << "Json解析失败";
return;
}
QJsonObject obj = doc.object();
QString strName = obj["name"].toString();
int nAge = obj["age"].toInt();
bool bStudent = obj["isStudent"].toBool();
qDebug() << "名字:" << strName;
qDebug() << "年龄:" << nAge;
qDebug() << "是否学生:" << bStudent;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// Set up code that uses the Qt event loop here.
// Call a.quit() or a.exit() to quit the application.
// A not very useful example would be including
// #include <QTimer>
// near the top of the file and calling
// QTimer::singleShot(5000, &a, &QCoreApplication::quit);
// which quits the application after 5 seconds.
// If you do not need a running Qt event loop, remove the call
// to a.exec() or use the Non-Qt Plain C++ Application template.
PraseJson();
return a.exec();
}
代码运行结果:
二、解析嵌套Json对象
void PraseJson2()
{
QString strJson = R"({
"person":{
"name":"李四",
"address":{
"city":"北京",
"street":"长安街"
}
},
"hobbies":["读书","音乐","运动"]
})";
QJsonDocument doc = QJsonDocument::fromJson(strJson.toUtf8());
if(doc.isNull() || !doc.isObject())
{
qDebug() << "Json解析失败";
return;
}
QJsonObject rootObj = doc.object();
QJsonObject personObj = rootObj["person"].toObject();
QJsonObject addressObj = personObj["address"].toObject();
QString strName = personObj["name"].toString();
qDebug() << "名字:" << strName;
QString strCity = addressObj["city"].toString();
qDebug() << "城市" << strCity;
QString strStreet = addressObj["street"].toString();
qDebug() << "街道:" << strStreet;
QJsonArray arr = rootObj["hobbies"].toArray();
qDebug() << "爱好:";
for (const QJsonValue& value: arr)
{
qDebug() << value.toString();
}
}
代码运行结果:
三、解析Json数组
void PraseJson3()
{
QString strJson = R"([
{"name":"王五","age":30},
{"name":"赵六","age":35},
{"name":"张三","age":20}
])";
QJsonDocument doc = QJsonDocument::fromJson(strJson.toUtf8());
if(doc.isNull())
{
qDebug() << "Json解析失败";
return;
}
if(doc.isArray())
{
QJsonArray arr = doc.array();
for(const QJsonValue& value:arr)
{
QJsonObject obj = value.toObject();
qDebug() << "名字:"<< obj["name"].toString() << ",年龄:" << obj["age"].toInt();
}
}
}
代码运行结果:
四、错误处理
void parseJsonWithErrorHandling() {
QString jsonString = R"({"invalid": json})"; // 无效的JSON
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8(), &error);
if (error.error != QJsonParseError::NoError) {
qDebug() << "JSON解析错误:" << error.errorString();
return;
}
if (doc.isNull()) {
qDebug() << "文档为空";
return;
}
// 安全地获取值
QJsonObject obj = doc.object();
QString value = obj.value("key").toString("默认值"); // 如果key不存在,返回默认值
// 检查值类型
if (obj.contains("key") && obj["key"].isString()) {
// 安全处理
}
}
五、构建Json对象
void createJson() {
QJsonObject person;
person["name"] = "张三";
person["age"] = 30;
QJsonArray hobbies;
hobbies.append("读书");
hobbies.append("游泳");
hobbies.append("编程");
person["hobbies"] = hobbies;
QJsonObject address;
address["city"] = "上海";
address["street"] = "南京路";
person["address"] = address;
QJsonDocument doc(person);
QString jsonString = doc.toJson(QJsonDocument::Indented);
qDebug() << "生成的JSON:";
qDebug() << jsonString;
}
代码运行结果:
注意事项
- 编码问题: 确保JSON字符串使用UTF-8编码
- 错误处理: 总是检查解析是否成功
- 类型安全: 在访问值之前检查其类型
- 内存管理: Qt的JSON类使用隐式共享,无需担心深拷贝性能问题
常用方法
QJsonDocument::fromJson()
- 从字符串创建文档QJsonObject::value()
- 安全获取值(可指定默认值)QJsonValue::toInt()
,toString()
,toBool()
- 类型转换QJsonObject::contains()
- 检查键是否存在QJsonValue::isObject()
,isArray()
,isString()
- 检查值类型
: Qt的JSON类使用隐式共享,无需担心深拷贝性能问题