个人技术分享

项目场景:

需要表格记录json数据,使用Qtreeview显示并修改,使用开源的第三方类QJsonModel,即可快速完成。


问题描述:

使用中发现一个问题:当Qtreeview修改完毕,从Model获取保存后的Json数据时,发生了异常,

例如当时传入的数据是:

"{\"ID\":555, \"AGE\":30, \"NUMBER\":11}";

修改555->666,得到的数据却是:

"{\"ID\":\"666\", \"AGE\":\"30\", \"NUMBER\":\"11\"}";

原因分析:

猜测model的返回,将value和key都当做了String处理,所以判断是arrayToJson()或者objectToJson()的问题,进一步发现都使用了genJson(mRootItem),继续看发现原代码中只对bool做了处理,其余一律默认String。

QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const
{
    auto type   = item->type();
    int  nchild = item->childCount();

    if (QJsonValue::Object == type) {
        QJsonObject jo;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            auto key = ch->key();
            jo.insert(key, genJson(ch));
        }
        return  jo;
    } else if (QJsonValue::Array == type) {
        QJsonArray arr;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            arr.append(genJson(ch));
        }
        return arr;
    } else {
        QJsonValue va;
        switch(item->value().type()) {
        case QVariant::Bool: {
            va = item->value().toBool();
            break;
        }
        default:
            va = item->value().toString();
            break;
        }
        (item->value());
        return va;
    }
}

解决方案:

更改判断条件,具体的根据需要填充不同数据类型,这样返回就是正确的值了,更改后的代码如下:

QJsonValue QJsonModel::genJson(QJsonTreeItem *item) const
{
    auto type   = item->type();
    int  nchild = item->childCount();

    if (QJsonValue::Object == type) {
        QJsonObject jo;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            auto key = ch->key();
            jo.insert(key, genJson(ch));
        }
        return  jo;
    } else if (QJsonValue::Array == type) {
        QJsonArray arr;
        for (int i = 0; i < nchild; ++i) {
            auto ch = item->child(i);
            arr.append(genJson(ch));
        }
        return arr;
    } else {
        QJsonValue va;
        switch(item->value().type()) {
        case QVariant::Bool: {
            va = item->value().toBool();
            break;
        }
        case QVariant::Int:
            va = item->value().toInt(); 
            break;
        case QVariant::UInt:
        case QVariant::LongLong:{
            va = item->value().toLongLong(); 
            break;
        }
        case QVariant::ULongLong: 
        case QVariant::Double: {
            va = item->value().toDouble();
            break;
        }
        // 添加其他 QVariant 类型的处理
        default: {
            va = item->value().toString();
            break;
        }
        }
        return va;
    }
}

这样就可以通过QByteArray json(bool compact = false)这个方法得到正确的数据类型的值。

"{\"ID\":666, \"AGE\":30, \"NUMBER\":11}";