diff options
| author | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-08-07 14:57:11 +0200 |
|---|---|---|
| committer | Sona Kurazyan <sona.kurazyan@qt.io> | 2020-08-13 19:36:58 +0200 |
| commit | 1df02b5f980b01a4e42f32061f1cba696b6a22e9 (patch) | |
| tree | d4962719806e06bba93831d5ee08d12124ac5bcc /src/corelib/serialization/qjsonvalue.cpp | |
| parent | 5b76414b43ee0ffabf292b4c6535f15e42613f1b (diff) | |
Fix conversions to JSON from QVariant
After reimplementing Qt JSON support on top of CBOR, there were
unintended behavior changes when converting QVariant{, List, Map} to
QJson{Value, Array, List} due to reusing the code for converting
QVariant* types to CBOR types, and from CBOR types to corresponding JSON
types. In particular, conversions from QVariant containing QByteArray to
JSON has been affected: according to RFC 7049, when converting from
CBOR to JSON, raw byte array data must be encoded in base64url when
converting to a JSON string. As a result QVariant* types containing
QByteArray data ended up base64url-encoded when converted to JSON,
instead of converting using QString::fromUtf8() as before.
There were also differences when converting QRegularExpression.
Reverted the behavior changes by adding a flag to internal methods for
converting CBOR to JSON, to distinguish whether the conversion is done
from QVariant* or CBOR types. These methods now will fall back to the old
behavior, if the conversion is done using QJson*::fromVariant*().
Additionally fixed QJsonValue::fromVariant conversion for NaN and
infinities: they should always convert to QJsonValue::Null. This works
correctly when converting from variant to QJsonArray/QJsonObject, but has
been wrong for QJsonValue.
Added more tests to verify the expected behavior.
[ChangeLog][Important Behavior Changes] Restored pre-5.15.0 behavior
when converting from QVariant* to QJson* types. Unforeseen consequences
of changes in 5.15.0 caused QByteArray data to be base64url-encoded; the
handling of QRegularExpression was also unintentionally changed. These
conversions are now reverted to the prior behavior. Additionally fixed
QJsonValue::fromVariant conversions for NaN and infinities: they should
always convert to QJsonValue::Null.
Fixes: QTBUG-84739
Change-Id: Iaee667d00e5363906eedbb67948b7b39c9d0bc78
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/serialization/qjsonvalue.cpp')
| -rw-r--r-- | src/corelib/serialization/qjsonvalue.cpp | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/src/corelib/serialization/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 34fa84cdc18..0f922f521ac 100644 --- a/src/corelib/serialization/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp @@ -351,7 +351,6 @@ void QJsonValue::swap(QJsonValue &other) noexcept error cases as e.g. accessing a non existing key in a QJsonObject. */ - /*! Converts \a variant to a QJsonValue and returns it. @@ -461,7 +460,11 @@ void QJsonValue::swap(QJsonValue &other) noexcept For other types not listed above, a conversion to string will be attempted, usually but not always by calling QVariant::toString(). If the conversion fails the value is replaced by a null JSON value. Note that - QVariant::toString() is also lossy for the majority of types. + QVariant::toString() is also lossy for the majority of types. For example, + if the passed QVariant is representing raw byte array data, it is recommended + to pre-encode it to \l {https://www.ietf.org/rfc/rfc4648.txt}{Base64} (or + another lossless encoding), otherwise a lossy conversion using QString::fromUtf8() + will be used. Please note that the conversions via QVariant::toString() are subject to change at any time. Both QVariant and QJsonValue may be extended in the @@ -488,8 +491,10 @@ QJsonValue QJsonValue::fromVariant(const QVariant &variant) return QJsonValue(variant.toLongLong()); Q_FALLTHROUGH(); case QMetaType::Float: - case QMetaType::Double: - return QJsonValue(variant.toDouble()); + case QMetaType::Double: { + double v = variant.toDouble(); + return qt_is_finite(v) ? QJsonValue(v) : QJsonValue(); + } case QMetaType::QString: return QJsonValue(variant.toString()); case QMetaType::QStringList: |
