关于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 的对比


版权声明:本文为hp_cpp原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。