关于QJson能解析的最大数据长度的源码分析

关于QJson能解析的最大数据长度的源码分析

最近在使用QJson的时候,发现在60Mb+不到70Mb的时候,就会解析失败。我们看看Qt中有没有对QJson能解析的数据长度的限制。

在文件Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\serialization\qjsondocument.cpp
第392-396行

QJsonDocument QJsonDocument::fromJson(const QByteArray &json, QJsonParseError *error)
{
    QJsonPrivate::Parser parser(json.constData(), json.length());
    return parser.parse(error);
}

在文件:

QJsonDocument Parser::parse(QJsonParseError *error)
{
//其余省略
    if (token == BeginArray) {
        if (!parseArray())
            goto error;
    } else if (token == BeginObject) {
        if (!parseObject())
            goto error;
    } else {
        lastError = QJsonParseError::IllegalValue;
        goto error;
    }
//其余省略
    return QJsonDocument();
}

如果json字符串是Array头的,则调用parseArray(),是以Object开头的,则调用parseObject()

我们先看parseArray()
在这里插入图片描述
在Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\serialization\qjsonparser.cpp

第607行的bool Parser::parseValue(QJsonPrivate::Value *val, int baseOffset)函数中
在这里插入图片描述

我们看看这个Value::MaxSize是多少

在Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\serialization\qjson_p.h
第528行
在这里插入图片描述
最大限制为MaxSize = (1<<27) - 1
我们知道1kb = 2的10次方 bit, 也就是1024 bit
1MB = 2的20次方 bit,也就是 1Mb = 1024*1024 bit

1<<27,也就是2的26次方
(2的26次方) 除以 (2的20次方) = 2的6次方,也就是64Mb

MaxSize = 64Mb - 1

结论:QJson能解析的最大数据为64Mb左右,简单来记就是不超过64Mb

这个baseOffset是多少呢?
刚才在parseArray()开头已经看到了:

int arrayOffset = reserveSpace(sizeof(QJsonPrivate::Array));

在这里插入图片描述

我们再看看这个sizeof(QJsonPrivate::Array)是多少

在Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\serialization\qjson_p.h文件中:

class Base
{
public:
    qle_uint size;
    union {
        uint _dummy;
        qle_bitfield<0, 1> is_object;
        qle_bitfield<1, 31> length;
    };
    offset tableOffset;
    // content follows here

    inline bool isObject() const { return !!is_object; }
    inline bool isArray() const { return !isObject(); }

    inline offset *table() const { return (offset *) (((char *) this) + tableOffset); }

    int reserveSpace(uint dataSize, int posInTable, uint numItems, bool replace);
    void removeItems(int pos, int numItems);
};

class Array : public Base
{
public:
    inline Value at(int i) const;
    inline Value &operator [](int i);

    bool isValid(int maxSize) const;
};

大家可以知道sizeof(QJsonPrivate::Array)这个是多少了,其实它是一个很小的数。

最后我们再来看一下QJsonParseError::DocumentTooLarge这个枚举最终怎么和字符串对应起来的

Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\serialization\qjsondocument.cpp
第53-77行:

struct Q_CORE_EXPORT QJsonParseError
{
    enum ParseError {
        NoError = 0,
        UnterminatedObject,
        MissingNameSeparator,
        UnterminatedArray,
        MissingValueSeparator,
        IllegalValue,
        TerminationByNumber,
        IllegalNumber,
        IllegalEscapeSequence,
        IllegalUTF8String,
        UnterminatedString,
        MissingObject,
        DeepNesting,
        DocumentTooLarge,
        GarbageAtEnd
    };

    QString    errorString() const;

    int        offset;
    ParseError error;
};

qjsonparser.cp
第141行的QString QJsonParseError::errorString()中
在这里插入图片描述
DocumentTooLarge对应的是JSONERR_DOC_LARGE

第66行到80行定义了一些宏:
在这里插入图片描述
这个QT_TRANSLATE_NOOP 是什么呢?

在Qt\Qt5.14.2\5.14.2\Src\qtbase\src\corelib\global\qglobal.h
文件中:
在这里插入图片描述
JSONERR_DOC_LARGE其实就是"too large document”字符串

参考:

Qt5 中的 Json 模块与 JsonCpp 的对比

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
使用 QJson 库可以解析 JSON 文件。以下是解析 JSON 文件的基本步骤: 1. 包含 QJson 库头文件: ```cpp #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> ``` 2. 从文件中读取 JSON 数据: ```cpp QFile file("data.json"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QByteArray jsonData = file.readAll(); file.close(); ``` 3. 将 JSON 数据解析成 QJsonDocument 对象: ```cpp QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); ``` 4. 从 QJsonDocument 对象中获取 QJsonObject 或 QJsonArray: ```cpp if (jsonDoc.isObject()) { QJsonObject jsonObj = jsonDoc.object(); // 处理 QJsonObject 对象 } else if (jsonDoc.isArray()) { QJsonArray jsonArray = jsonDoc.array(); // 处理 QJsonArray 对象 } ``` 5. 从 QJsonObject 或 QJsonArray 中获取具体的 JSON 数据: ```cpp // 从 QJsonObject 中获取字符串数据 QString name = jsonObj["name"].toString(); // 从 QJsonArray 中获取整数数据 int age = jsonArray[0].toInt(); ``` 完整的代码示例: ```cpp #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> #include <QFile> void parseJsonFile(const QString &fileName) { QFile file(fileName); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return; QByteArray jsonData = file.readAll(); file.close(); QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); if (jsonDoc.isObject()) { QJsonObject jsonObj = jsonDoc.object(); QString name = jsonObj["name"].toString(); int age = jsonObj["age"].toInt(); qDebug() << "Name: " << name << ", Age: " << age; } else if (jsonDoc.isArray()) { QJsonArray jsonArray = jsonDoc.array(); foreach (const QJsonValue & value, jsonArray) { int age = value.toInt(); qDebug() << "Age: " << age; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值