QT框架下的文本操作(三)

6 篇文章 0 订阅

JSON文件

json在网络通信中经常被使用,特别是在与 pyhton、java服务交互时,常常要求传递、解析 json。

json文件格式

json标准符号
1.花括号 {}
2.双引号 ""
3.冒号 :
4.逗号 ,
5.中括号 []
json示例
{
	"id" : 1,
	"name" : "Tim",
	"isFemal" : false,
	"relevant" : null,
	"children" : ["Jack","John","James"],
	"address" : {
		"street" : "Wiessenstrasse",
		"postCode" : 100001
	}
}

其中,id 为数值,name 为字符串,isFemal为布尔值,relevant为空,children为数组,address为对象。

json解析

这里使用QT中的 QJson模块来解析、构造 json。

// Json解析模块定义
struct JsonPrivate {
	JsonPrivate(const QString &jsonOrJsonFilePath, bool fromFile);

	void setValue(QJsonObject &parent, const QString &path, const QJsonValue &newValue);
	QJsonValue getValue(const QString &path, const QJsonObject &fromNode) const;

    QJsonObject root;    // Json 的根节点
    QJsonDocument doc;   // Json 的文档对象
    bool valid = true;   // Json 是否有效
    QString errorString; // Json 无效时的错误信息
};
// 在构造函数中读取、解析 json
JsonPrivate::JsonPrivate(const QString &jsonOrJsonFilePath, bool fromFile) {
	QByteArray json("{}"); // json 的内容

    // 如果传人的是 JsonUtil 文件的路径,则读取内容
	if (fromFile) {
		QFile file(jsonOrJsonFilePath);

		if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
			json = file.readAll();
        } else {
            valid = false;
            errorString = QString("Cannot open the file: %1").arg(jsonOrJsonFilePath);
            qDebug() << errorString;
            return;
        }
    } else {
		json = jsonOrJsonFilePath.toUtf8();
	}

    // 解析 Json
	QJsonParseError error;
    doc = QJsonDocument::fromJson(json, &error);

    if (QJsonParseError::NoError == error.error) {
        root = doc.object();
    } else {
        valid = false;
        errorString = QString("%1\nOffset: %2").arg(error.errorString()).arg(error.offset);
        qDebug() << errorString;
    }
}
属性值读取
// 读取属性的值,如果 fromNode 为空,则从跟节点开始访问
QJsonValue JsonPrivate::getValue(const QString &path, const QJsonObject &fromNode) const {
    // 1. 确定搜索的根节点,如果 fromNode 为空则搜索的根节点为 root
    // 2. 把 path 使用分隔符 . 分解成多个属性名字
    // 3. 从搜索的根节点开始向下查找到倒数第二个属性名字对应的 QJsonObject parent
    //    如 "user.address.street",要设置的属性为 street,它的 parent 是 address
    // 4. 返回 parent 中属性名为倒数第一个属性名字对应的属性值

    // [1] 确定搜索的根节点,如果 fromNode 为空则搜索的根节点为 root
    // [2] 把 path 使用分隔符 . 分解成多个属性名字
    QJsonObject parent = fromNode.isEmpty() ? root : fromNode;
    QStringList names  = path.split(QRegularExpression("\\."));

    // [3] 从搜索的根节点开始向下查找到倒数第二个属性名字对应的 QJsonObject parent
    int size = names.size();
    for (int i = 0; i < size - 1; ++i) {
        if (parent.isEmpty()) {
            return QJsonValue();
        }

        parent = parent.value(names.at(i)).toObject();
    }

    // [4] 返回 parent 中属性名为倒数第一个属性名字对应的属性值
    return parent.value(names.last());
}
属性值设置
void JsonPrivate::setValue(QJsonObject &parent, const QString &path, const QJsonValue &newValue) {
    const int indexOfDot   = path.indexOf('.');     // 第一个 . 的位置
    const QString property = path.left(indexOfDot); // 第一个 . 之前的内容,如果 indexOfDot 是 -1 则返回整个字符串
    const QString restPath = (indexOfDot > 0) ? path.mid(indexOfDot + 1) : QString(); // 第一个 . 后面的内容

    QJsonValue fieldValue = parent[property];

    if(restPath.isEmpty()) {
        // 找到要设置的属性
        fieldValue = newValue;
    } else {
        // 路径中间的属性,递归访问它的子属性
        QJsonObject obj = fieldValue.toObject();
        setValue(obj, restPath, newValue);
        fieldValue = obj; // 因为 QJsonObject 操作的都是对象的副本,所以递归结束后需要保存起来再次设置回 parent
    }

    parent[property] = fieldValue; // 如果不存在则会创建
}

有了 JsonPrivate 模块,我们就可以很方便的读取、修改 json文件了。
对于示例中的json,我们可以这样去读取、修改:

读取
// jsonString为示例中的json
JsonPrivate jsonUtil(jsonString,false);
// 读取id
int idValue = jsonUtil.getValue("id").toInt();
// 读取name
QString nameValue = jsonUtil.getValue("name").toString();
// 读取isFemal
bool isFemalValue = jsonUtil.getValue("isFemal").toBool();
// 读取children
QStringList childrenList;
QJsonArray array = jsonUtil.getValue("children").toArray();
for (QJsonArray::const_iterator iter = array.begin(); iter != array.end(); ++iter) {
	QJsonValue value = *iter;
	childrenList << value.toString();
}
// 读取address
QString streetValue = jsonUtil.getValue("address.street").toString();
int postCodeValue = jsonUtil.getValue("address.postCode").toInt();
修改
// jsonString为示例中的json
JsonPrivate jsonUtil(jsonString, false);
// 修改id
jsonUtil.setValue(jsonUtil.root, "id", 2);
// 修改name
jsonUtil.setValue(jsonUtil.root, "name", "Lily");
// 修改isFemal
jsonUtil.setValue(jsonUtil.root, "isFemal", true);
// 修改children
QStringList childrenList = QStringList() << "Kevin" << "Peter";
QJsonArray array;
foreach(const QString &str, childrenList) {
	array.append(str);
}
jsonUtil.setValue(jsonUtil.root, "children", array);
// 修改address
jsonUtil.setValue(jsonUtil.root, "address.street", "BaihuaRoad");
jsonUtil.setValue(jsonUtil.root, "address.postCode", 100002);

完整的文本操作源码,点击此处下载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值