Qt JSON文件解析详解
一、JSON格式介绍
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。
1、核心特点
- 轻量级: 相较于 XML 等其他数据格式,JSON 的结构更简洁,冗余更少。
- 文本格式: 基于纯文本,独立于编程语言,但使用了 JavaScript 对象字面量的语法。
- 可读性好: 结构清晰,格式简洁,便于人类理解和修改。
- 易于解析和生成: 各种编程语言都提供了简单易用的库来解析 JSON 字符串或生成 JSON 数据。
2、基本数据结构
JSON 主要使用两种结构来表示数据:
对象(Object):
- 表示为一对大括号
{}包围的无序集合。 - 集合由逗号分隔的 键值对 组成。
- 键(Key) 必须是一个用双引号
" "包围的字符串。 - 值(Value) 可以是字符串、数值、布尔值、null、对象或数组。
- 格式:
{ "key1": value1, "key2": value2, ... } - 示例:
{ "name": "张三", "age": 30, "isStudent": false }
- 表示为一对大括号
数组(Array):
- 表示为一对方括号
[]包围的有序集合。 - 集合由逗号分隔的值组成。
- 值可以是字符串、数值、布尔值、null、对象或数组。
- 格式:
[ value1, value2, ... ] - 示例:
["苹果", "香蕉", "橙子"][1, 2, 3, 4, 5][ {"name": "李四", "age": 25}, {"name": "王五", "age": 28} ]
- 表示为一对方括号
3、数据类型
JSON 值可以是以下数据类型:
- 字符串(String): 必须用双引号
" "包围。例如:"Hello, World!" - 数值(Number): 整数或浮点数。例如:
42,3.14159 - 布尔值(Boolean):
true或false(必须小写)。 - 空值(Null):
null(必须小写)。 - 对象(Object): 如上所述。
- 数组(Array): 如上所述。
4、语法规则
- 数据以键值对的形式组织。
- 键名(Key)必须是字符串,用双引号包裹。
- 值(Value)可以是字符串、数字、布尔值、数组、对象或 null。
- 数据由逗号分隔。
- 大括号
{}保存对象。 - 方括号
[]保存数组。
5、一个综合示例
{
"user": {
"name": "赵六",
"age": 35,
"address": {
"street": "科技路",
"city": "北京",
"country": "中国"
},
"isMarried": true,
"hobbies": ["阅读", "旅行", "摄影"],
"children": null
}
}
6、主要用途
- Web 应用程序的数据交换: 客户端(浏览器)和服务器之间传输数据(AJAX)。
- 配置文件: 许多软件使用 JSON 格式存储配置信息。
- API 接口: RESTful API 常使用 JSON 作为请求和响应的数据格式。
- NoSQL 数据库: 如 MongoDB 存储文档数据。
- 序列化数据: 将复杂的数据结构转换为字符串以便存储或传输。
7、注意事项
- JSON 不支持注释。不能在 JSON 文件中添加注释。
- 字符串必须使用双引号,单引号无效。
- 键名也必须使用双引号。
- JSON 文件通常使用
.json作为扩展名。
二、相关类介绍
在Qt中,JSON数据的解析主要通过以下核心类实现:
1、QJsonDocument
功能:处理完整的JSON文档,提供JSON数据的序列化与反序列化。
关键方法:
fromJson():将JSON字符串解析为QJsonDocument对象。toJson():将QJsonDocument转换为JSON字符串。isObject()/isArray():判断文档类型(对象或数组)。object()/array():获取文档中的QJsonObject或QJsonArray。
QString jsonStr = R"({"name": "Qt", "version": 6})";
QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8());
if (doc.isObject()) {
QJsonObject obj = doc.object();
QString name = obj["name"].toString(); // "Qt"
}
2、QJsonObject
功能:表示JSON中的对象(键值对集合)。
关键方法:
insert(key, value):插入键值对。value(key):获取指定键的值(返回QJsonValue)。keys():获取所有键的列表。remove(key):删除指定键。
QJsonObject obj;
obj.insert("language", "C++");
obj.insert("framework", "Qt");
// 遍历对象
for (const QString& key : obj.keys()) {
qDebug() << key << ":" << obj[key].toString();
}
3、QJsonArray
功能:表示JSON中的数组(有序值列表)。
关键方法:
append(value):向数组末尾添加值。at(index):获取索引处的值(返回QJsonValue)。size():获取数组长度。removeAt(index):删除指定索引的值。
QJsonArray arr;
arr.append(42);
arr.append("Qt6");
// 遍历数组
for (int i = 0; i < arr.size(); ++i) {
if (arr.at(i).isString()) {
qDebug() << arr.at(i).toString();
}
}
4、 QJsonValue
功能:封装JSON中的单一值(字符串、数字、布尔值、对象、数组等)。
关键方法:
toBool()/toString()/toDouble():转换为基本类型。toObject()/toArray():转换为QJsonObject或QJsonArray。isNull()/isUndefined():检查值类型。
QJsonValue val = obj.value("version");
if (val.isDouble()) {
int version = val.toInt(); // 6
}
5、QJsonParseError
功能:在解析JSON时捕获错误信息。
关键属性:
error:错误类型(如NoError、UnterminatedObject)。offset:错误在字符串中的位置。
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(jsonStr, &error);
if (error.error != QJsonParseError::NoError) {
qDebug() << "JSON解析错误:" << error.errorString();
}
三、示例
1、效果展示

2、源码分享
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QDebug>
#include <QFile>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 安装自定义消息处理器
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
qInstallMessageHandler(myMessageHandler);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
// 创建复杂JSON结构
QJsonObject root;
root.insert("projectName", "Qt6 JSON Demo");
root.insert("version", 6.2);
root.insert("active", true);
// 创建嵌套对象
QJsonObject author;
author.insert("name", "Zhang San");
author.insert("email", "zhangsan@example.com");
author.insert("department", "R&D");
root.insert("author", author);
// 创建对象数组
QJsonArray dependencies;
QJsonObject dep1;
dep1.insert("name", "QtCore");
dep1.insert("version", "6.2.4");
QJsonObject dep2;
dep2.insert("name", "QtNetwork");
dep2.insert("version", "6.2.4");
dep2.insert("optional", true);
dependencies.append(dep1);
dependencies.append(dep2);
root.insert("dependencies", dependencies);
// 创建配置对象
QJsonObject config;
config.insert("maxThreads", 8);
config.insert("timeout", 5000);
QJsonArray allowedIPs;
allowedIPs.append("192.168.1.1");
allowedIPs.append("10.0.0.0/24");
config.insert("allowedIPs", allowedIPs);
root.insert("config", config);
// 转换为JSON文档
QJsonDocument doc(root);
QString jsonString = doc.toJson(QJsonDocument::Indented);
qDebug() << "Generated JSON:\n" << jsonString;
// 解析JSON
QJsonParseError parseError;
QJsonDocument parsedDoc = QJsonDocument::fromJson(jsonString.toUtf8(), &parseError);
if (parseError.error != QJsonParseError::NoError) {
qDebug() << "Parse error:" << parseError.errorString();
return;
}
if (!parsedDoc.isObject()) {
qDebug() << "Document is not an object";
return;
}
QJsonObject rootObj = parsedDoc.object();
// 提取顶层数据
QString projectName = rootObj["projectName"].toString();
double version = rootObj["version"].toDouble();
bool isActive = rootObj["active"].toBool();
qDebug() << "\nProject:" << projectName;
qDebug() << "Version:" << version;
qDebug() << "Active:" << (isActive ? "Yes" : "No");
// 解析嵌套对象
if (rootObj.contains("author") && rootObj["author"].isObject()) {
QJsonObject authorObj = rootObj["author"].toObject();
qDebug() << "\nAuthor:" << authorObj["name"].toString()
<< "| Email:" << authorObj["email"].toString();
}
// 解析数组
if (rootObj.contains("dependencies") && rootObj["dependencies"].isArray()) {
QJsonArray depArray = rootObj["dependencies"].toArray();
qDebug() << "\nDependencies:";
for (int i = 0; i < depArray.size(); ++i) {
if (depArray[i].isObject()) {
QJsonObject dep = depArray[i].toObject();
QString name = dep["name"].toString();
QString version = dep["version"].toString();
bool optional = dep.contains("optional") ? dep["optional"].toBool() : false;
qDebug() << " -" << name << version << "(Optional:" << optional << ")";
}
}
}
// 解析复杂配置
if (rootObj.contains("config") && rootObj["config"].isObject()) {
QJsonObject configObj = rootObj["config"].toObject();
qDebug() << "\nConfiguration:";
qDebug() << "Max Threads:" << configObj["maxThreads"].toInt();
qDebug() << "Timeout:" << configObj["timeout"].toInt() << "ms";
if (configObj.contains("allowedIPs") && configObj["allowedIPs"].isArray()) {
QJsonArray ipArray = configObj["allowedIPs"].toArray();
qDebug() << "Allowed IPs:";
for (const QJsonValue &ip : ipArray) {
if (ip.isString()) {
qDebug() << " *" << ip.toString();
}
}
}
}
}

浙公网安备 33010602011771号