关于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”字符串
参考: