qt::JSON文件介绍和操作

引言:

https://github.com/0voice

JSON(JavaScript Object Notation)作为轻量级的数据交换格式,因结构清晰、可读性强、跨平台兼容等特性,被广泛用于配置文件、接口数据传输等场景。Qt 框架提供了完整的 JSON 处理模块(Qt Core 内置,无需额外依赖),可轻松实现 JSON 数据的构建、序列化、解析和错误处理。本文将结合实战代码,详细讲解如何在 Qt 中生成 JSON 配置文件,并完成解析与数据提取。

一、JSON 基础

1. JSON 核心结构

JSON 的核心组成是对象(Object)数组(Array),其中对象是最常用的结构(对应代码中的数据库配置存储):

  • 对象:用{}包裹,由键值对(key:value)组成,键必须是字符串(双引号包裹),值支持字符串、数字、布尔值、对象、数组、null
  • 键值对分隔符::(冒号),多个键值对 / 数组元素用,(逗号)分隔;
  • 嵌套结构:值可以是另一个对象(如代码中data键对应数据库配置对象)。

2. JSON 核心构造字符

JSON 语法依赖 6 个基础构造字符(规范定义),是解析和生成的核心规则:

构造字符 作用 示例
{/} 标记 JSON 对象的开始 / 结束 {"ip":"192.168.0.1"}
[/] 标记 JSON 数组的开始 / 结束 [1,2,3]
: 分隔键和值 "port":3308
, 分隔多个键值对 / 数组元素 "user":"root","password":"123456"

Qt 的 JSON 处理模块严格遵循该规范,任何违反规则的 JSON 数据都会触发解析错误。

二、Qt 处理 JSON 的核心类

Qt 通过 4 个核心类实现 JSON 的全流程处理,以下是类的职责与协作关系:

类名 核心职责 代码中的作用
QJsonObject 内存中存储 JSON 对象(键值对集合) 构建数据库配置对象、根配置对象
QJsonDocument JSON 文档封装器,实现序列化 / 反序列化 QJsonObject转为 JSON 字节流(写入)、解析文件字节流为对象(读取)
QJsonValue 通用值容器,实现类型判断与转换 提取键对应的值,转换为字符串 / 整数等具体类型
QJsonParseError 捕获 JSON 解析错误(类型、位置、描述) 校验解析是否成功,定位语法错误

三、实战 1:生成 JSON 配置文件(写入)

1. 核心需求

将 MySQL 数据库配置(IP、端口、用户名、密码)封装为 JSON 对象,写入本地jsonfile.json文件。

2. 代码拆解(对应on_pushButton_write_clicked

cpp 复制代码
void Dialog::on_pushButton_write_clicked()
{
    // 步骤1:构建嵌套JSON对象(数据库配置)
    QJsonObject mysqlInfo;// 子对象:存储数据库核心配置
    mysqlInfo.insert("ip","192.168.0.125");    // 字符串值
    mysqlInfo.insert("port",3308);             // 数字值(自动封装为QJsonValue)
    mysqlInfo.insert("user","root");
    mysqlInfo.insert("password","123456");

    // 步骤2:构建根JSON对象(包含状态码、描述、嵌套对象)
    QJsonObject jsonInfo;// 根对象:统一管理配置元信息和数据
    jsonInfo.insert("code",1);                  // 状态码(1=成功)
    jsonInfo.insert("dbmsg","MySQL数据库配置参数");// 配置描述
    jsonInfo.insert("data",mysqlInfo);          // 值为嵌套对象

    // 步骤3:封装为JSON文档(序列化前提)
    QJsonDocument jsonDocument;
    jsonDocument.setObject(jsonInfo);           // 将根对象绑定到文档

    // 步骤4:写入文件
    QFile file("./jsonfile.json");              // 文件路径(默认项目根目录)
    QString str;
    if(file.open(QIODevice::WriteOnly)){        // 只写模式打开文件
        // 序列化:QJsonDocument→JSON字节流(带缩进,可读性强)
        file.write(jsonDocument.toJson());      
        str="写入成功";
    }else {
        str="打开失败,写入失败";
    }
    QMessageBox::information(this,"写入对话框",str.toUtf8().data(),QMessageBox::Ok);
}

3. 关键解析

  • QJsonObject 构建 :通过insert(key, value)添加键值对,value支持字符串、数字等基础类型,Qt 会自动封装为QJsonValue
  • QJsonDocument 序列化QJsonObject本身无法直接写入文件,必须通过QJsonDocumenttoJson()方法转为符合 JSON 规范的字节流(默认带缩进,若需紧凑格式可传QJsonDocument::Compact);
  • 文件写入QFilewrite()方法接收字节流,完成最终的文件存储。

4. 生成的 JSON 文件内容

json

cpp 复制代码
{
    "code": 1,
    "dbmsg": "MySQL数据库配置参数",
    "data": {
        "ip": "192.168.0.125",
        "port": 3308,
        "user": "root",
        "password": "123456"
    }
}

四、实战 2:解析 JSON 配置文件(读取)

1. 核心需求

读取jsonfile.json文件,解析 JSON 数据,提取数据库配置,并完成错误校验(文件打开、解析语法、数据合法性)。

2. 代码拆解(对应on_pushButton_read_clicked

cpp 复制代码
void Dialog::on_pushButton_read_clicked()
{
    QString strjson;
    QString strmsg;
    // 步骤1:读取文件内容
    QFile readFIle("./jsonfile.json");
    if(readFIle.open(QIODevice::ReadOnly)){     // 只读模式打开文件
        strjson=readFIle.readAll();             // 读取所有字节流
        qDebug()<<"打开文件成功";
    } else {
        QMessageBox::critical(this,"错误","文件打开失败!");
        return;
    }

    // 步骤2:解析JSON字节流(反序列化)
    QJsonParseError jsonError;                  // 错误信息容器
    // 反序列化:字节流→QJsonDocument,错误信息存入jsonError
    QJsonDocument jsonDoc=QJsonDocument::fromJson(strjson.toUtf8(),&jsonError);
    
    // 步骤3:校验解析结果(文档非空 + 无语法错误)
    if(!jsonDoc.isEmpty()&&(jsonError.error==QJsonParseError::NoError))
    {
        // 步骤4:提取根对象
        QJsonObject jsonObject=jsonDoc.object();
        
        // 步骤5:提取关键值并校验数据合法性
        QJsonValue code=jsonObject.value("code");
        QJsonValue data=jsonObject.value("data");
        // 校验:键存在 + code值为1 + data是对象
        if(code.isUndefined()||
                data.isUndefined()||
                code.toDouble()!=1||
                !data.isObject()){
            qDebug()<<"JSON转换数据有问题";
            QMessageBox::critical(this,"错误","转换JSON数据错误,请重新检查?");
            return;
        }

        // 步骤6:提取嵌套对象的配置参数
        QJsonObject json1=data.toObject();      // 转为嵌套对象
        QJsonValue dbip=json1.value("ip");
        QJsonValue dbport=json1.value("port");
        QJsonValue dbuser=json1.value("user");
        QJsonValue dbpassword=json1.value("password");

        // 步骤7:校验嵌套键是否存在
        if(dbip.isUndefined()||dbport.isUndefined()||dbuser.isUndefined()||dbpassword.isUndefined())
        {
            qDebug()<<"接口错误,请重新检查?";
            QMessageBox::critical(this,"错误","接口错误,请重新检查?");
            return;
        }

        // 步骤8:类型转换(QJsonValue→具体类型)
        QString strip=dbip.toString();          // 字符串转换
        int intport=dbport.toInt();             // 数字转换(JSON数字默认Double,自动取整)
        QString struser=dbuser.toString();
        QString strpassword=dbpassword.toString();

        // 步骤9:校验参数非空
        if(strip.isEmpty()||struser.isEmpty()||strpassword.isEmpty()){
            qDebug()<<"此数据项,不能为空";
            QMessageBox::critical(this,"错误","此项不能为空");
            return;
        }

        // 步骤10:输出结果
        strmsg+="【JSON配置参数】";
        strmsg+="\n数据库IP地址:"+strip;
        strmsg+="\n数据库端口:"+QString::number(intport,10);
        strmsg+="\n数据库用户:"+struser;
        strmsg+="\n数据库密码:"+strpassword;
        QMessageBox::information(this,"信息",strmsg.toUtf8().data());
    } else {
        // 解析语法错误处理
        QMessageBox::critical(this,"错误","JSON解析失败:"+jsonError.errorString());
    }
}

3. 关键解析

  • 文件读取 :通过QFile::readAll()获取 JSON 字节流,需先校验文件是否打开成功;
  • 反序列化与错误校验QJsonDocument::fromJson()完成字节流→文档的转换,QJsonParseError捕获语法错误(如缺少逗号、引号不匹配);
  • QJsonValue 类型安全转换
    • JSON 中所有数字均为Double类型,需通过toInt()/toDouble()转换;
    • 转换前需通过isUndefined()/isObject()等判断类型,避免转换失败;
  • 多层校验:从 "文件打开→语法解析→数据合法性→参数非空" 逐层校验,确保程序鲁棒性。

五、Qt 处理 JSON 的常见问题与最佳实践

1. 路径问题

  • 代码中./jsonfile.json为相对路径,默认生成 / 读取位置为Qt 项目根目录 (Qt Creator 运行时),若双击exe运行则在exe所在目录;
  • 推荐使用绝对路径:QCoreApplication::applicationDirPath() + "/jsonfile.json"(与exe同目录)。

2. 类型转换避坑

  • JSON 无 "整数类型",所有数字解析为DoubletoInt()会自动取整(如 3308.0→3308);
  • 字符串含特殊字符(如\")时,Qt 会自动转义,无需手动处理。

3. 错误处理

  • 必须校验QJsonParseError::error是否为NoError,避免解析非法 JSON;
  • 键值提取后需用isUndefined()判断是否存在,避免空值导致程序异常;
  • 错误提示需具体(如区分 "文件打开失败" 和 "JSON 语法错误"),便于调试。

4. 性能优化

  • 生成大 JSON 时,使用QJsonDocument::Compact模式(无缩进),减少文件体积;
  • 解析大 JSON 时,避免一次性readAll(),可分段读取(需确保 JSON 结构完整)。

六、总结

Qt 通过QJsonObject(构建数据)、QJsonDocument(序列化 / 反序列化)、QJsonValue(类型转换)、QJsonParseError(错误处理)的组合,实现了 JSON 数据的全流程管理。核心流程可总结为:

cpp 复制代码
写入:QJsonObject(构建)→ QJsonDocument(序列化)→ QFile(写入)
读取:QFile(读取)→ QJsonDocument(反序列化)→ QJsonObject(提取)→ QJsonValue(转换)

该方案无需依赖第三方库,跨平台兼容性强,既适用于简单配置文件(如本文的数据库配置),也可扩展到复杂 JSON 数据(如接口返回的嵌套数组 / 对象),是 Qt 开发中处理 JSON 的标准方案。

相关推荐
ULTRA??40 分钟前
Qt 中基于 QVector3D 实现的直线交点+法向量计算函数
c++·qt
SongYuLong的博客1 小时前
C++基于jsoncpp开源库json数据操作
开发语言·c++·json
笨鸟要努力11 小时前
Qt C++ windows 设置系统时间
c++·windows·qt
友友马13 小时前
『QT』事件处理机制详解 (一)
开发语言·qt
R_.L13 小时前
【QT】常用控件(概述、QWidget核心属性)
qt·控件
烧酒同学13 小时前
【Qt】QScrollArea的滑动条无法拖动(已解决)
qt·bug
10km14 小时前
java:json-path支持fastjson作为JSON解析提供者的技术实现
java·json·fastjson·json-path
扶尔魔ocy20 小时前
【QT常用技术讲解】多线程和线程池
qt·多线程·thread
宠..20 小时前
创建文本框控件
linux·运维·服务器·开发语言·qt