From a06148e3414744cc4153f40a5610bad53ffebd62 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 10 Jul 2017 13:42:28 +0200 Subject: [PATCH] Improve symmetry of variant json conversions Make QVariant::toJsonValue do conversions as well as QJsonValue::fromVariant. Change-Id: I175d43677061470691e2e0104a800be355fbbd3d Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 105 ++++++++++++++++++++++++- tests/auto/corelib/json/tst_qtjson.cpp | 68 +++++++++++----- 2 files changed, 151 insertions(+), 22 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index e6262124fb..29af0647ea 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -938,6 +938,107 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; } break; +#ifndef QT_BOOTSTRAPPED + case QMetaType::QJsonValue: + switch (d->type) { + case QMetaType::Nullptr: + *static_cast(result) = QJsonValue(QJsonValue::Null); + break; + case QVariant::Bool: + *static_cast(result) = QJsonValue(d->data.b); + break; + case QMetaType::Int: + case QMetaType::UInt: + case QMetaType::Double: + case QMetaType::Float: + case QMetaType::ULong: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::ULongLong: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::Char: + case QMetaType::SChar: + case QMetaType::Short: + *static_cast(result) = QJsonValue(qConvertToRealNumber(d, ok)); + Q_ASSERT(ok); + break; + case QVariant::String: + *static_cast(result) = QJsonValue(*v_cast(d)); + break; + case QVariant::StringList: + *static_cast(result) = QJsonValue(QJsonArray::fromStringList(*v_cast(d))); + break; + case QVariant::List: + *static_cast(result) = QJsonValue(QJsonArray::fromVariantList(*v_cast(d))); + break; + case QVariant::Map: + *static_cast(result) = QJsonValue(QJsonObject::fromVariantMap(*v_cast(d))); + break; + case QVariant::Hash: + *static_cast(result) = QJsonValue(QJsonObject::fromVariantHash(*v_cast(d))); + break; + case QMetaType::QJsonObject: + *static_cast(result) = *v_cast(d); + break; + case QMetaType::QJsonArray: + *static_cast(result) = *v_cast(d); + break; + case QMetaType::QJsonDocument: { + QJsonDocument doc = *v_cast(d); + *static_cast(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object()); + break; + } + default: + *static_cast(result) = QJsonValue(QJsonValue::Undefined); + return false; + } + break; + case QMetaType::QJsonArray: + switch (d->type) { + case QVariant::StringList: + *static_cast(result) = QJsonArray::fromStringList(*v_cast(d)); + break; + case QVariant::List: + *static_cast(result) = QJsonArray::fromVariantList(*v_cast(d)); + break; + case QMetaType::QJsonValue: + if (!v_cast(d)->isArray()) + return false; + *static_cast(result) = v_cast(d)->toArray(); + break; + case QMetaType::QJsonDocument: + if (!v_cast(d)->isArray()) + return false; + *static_cast(result) = v_cast(d)->array(); + break; + default: + return false; + } + break; + case QMetaType::QJsonObject: + switch (d->type) { + case QVariant::Map: + *static_cast(result) = QJsonObject::fromVariantMap(*v_cast(d)); + break; + case QVariant::Hash: + *static_cast(result) = QJsonObject::fromVariantHash(*v_cast(d)); + break; + case QMetaType::QJsonValue: + if (!v_cast(d)->isObject()) + return false; + *static_cast(result) = v_cast(d)->toObject(); + break; + case QMetaType::QJsonDocument: + if (v_cast(d)->isArray()) + return false; + *static_cast(result) = v_cast(d)->object(); + break; + default: + return false; + } + break; +#endif default: #ifndef QT_NO_QOBJECT if (d->type == QVariant::String || d->type == QVariant::ByteArray) { @@ -3106,8 +3207,8 @@ bool QVariant::canConvert(int targetTypeId) const } } - if (currentType == QMetaType::QJsonValue) { - switch (targetTypeId) { + if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) { + switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) { case QMetaType::Nullptr: case QMetaType::QString: case QMetaType::Bool: diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp index 417b9a4173..1e3604ac9e 100644 --- a/tests/auto/corelib/json/tst_qtjson.cpp +++ b/tests/auto/corelib/json/tst_qtjson.cpp @@ -80,7 +80,10 @@ private Q_SLOTS: void undefinedValues(); + void fromVariant_data(); void fromVariant(); + void toVariant_data(); + void toVariant(); void fromVariantMap(); void fromVariantHash(); void toVariantMap(); @@ -1095,8 +1098,11 @@ void tst_QtJson::undefinedValues() QCOMPARE(array.at(-1).type(), QJsonValue::Undefined); } -void tst_QtJson::fromVariant() +void tst_QtJson::fromVariant_data() { + QTest::addColumn("variant"); + QTest::addColumn("jsonvalue"); + bool boolValue = true; int intValue = -1; uint uintValue = 1; @@ -1119,44 +1125,66 @@ void tst_QtJson::fromVariant() variantList.append(doubleValue); variantList.append(stringValue); variantList.append(stringList); - variantList.append(QVariant()); + variantList.append(QVariant::fromValue(nullptr)); QJsonArray jsonArray_variant; jsonArray_variant.append(boolValue); jsonArray_variant.append(floatValue); jsonArray_variant.append(doubleValue); jsonArray_variant.append(stringValue); jsonArray_variant.append(jsonArray_string); - jsonArray_variant.append(QJsonValue()); + jsonArray_variant.append(QJsonValue(QJsonValue::Null)); QVariantMap variantMap; variantMap["bool"] = boolValue; variantMap["float"] = floatValue; variantMap["string"] = stringValue; variantMap["array"] = variantList; + QVariantHash variantHash; + variantHash["bool"] = boolValue; + variantHash["float"] = floatValue; + variantHash["string"] = stringValue; + variantHash["array"] = variantList; QJsonObject jsonObject; jsonObject["bool"] = boolValue; jsonObject["float"] = floatValue; jsonObject["string"] = stringValue; jsonObject["array"] = jsonArray_variant; - QCOMPARE(QJsonValue::fromVariant(QVariant::fromValue(nullptr)), QJsonValue(QJsonValue::Null)); - QCOMPARE(QJsonValue::fromVariant(QVariant(boolValue)), QJsonValue(boolValue)); - QCOMPARE(QJsonValue::fromVariant(QVariant(intValue)), QJsonValue(intValue)); - QCOMPARE(QJsonValue::fromVariant(QVariant(uintValue)), QJsonValue(static_cast(uintValue))); - QCOMPARE(QJsonValue::fromVariant(QVariant(longlongValue)), QJsonValue(longlongValue)); - QCOMPARE(QJsonValue::fromVariant(QVariant(ulonglongValue)), QJsonValue(static_cast(ulonglongValue))); - QCOMPARE(QJsonValue::fromVariant(QVariant(floatValue)), QJsonValue(static_cast(floatValue))); - QCOMPARE(QJsonValue::fromVariant(QVariant(doubleValue)), QJsonValue(doubleValue)); - QCOMPARE(QJsonValue::fromVariant(QVariant(stringValue)), QJsonValue(stringValue)); - QCOMPARE(QJsonValue::fromVariant(QVariant(stringList)), QJsonValue(jsonArray_string)); - QCOMPARE(QJsonValue::fromVariant(QVariant(variantList)), QJsonValue(jsonArray_variant)); - QCOMPARE(QJsonValue::fromVariant(QVariant(variantMap)), QJsonValue(jsonObject)); + QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QJsonValue(QJsonValue::Null); + QTest::newRow("bool") << QVariant(boolValue) << QJsonValue(boolValue); + QTest::newRow("int") << QVariant(intValue) << QJsonValue(intValue); + QTest::newRow("uint") << QVariant(uintValue) << QJsonValue(static_cast(uintValue)); + QTest::newRow("longlong") << QVariant(longlongValue) << QJsonValue(longlongValue); + QTest::newRow("ulonglong") << QVariant(ulonglongValue) << QJsonValue(static_cast(ulonglongValue)); + QTest::newRow("float") << QVariant(floatValue) << QJsonValue(floatValue); + QTest::newRow("double") << QVariant(doubleValue) << QJsonValue(doubleValue); + QTest::newRow("string") << QVariant(stringValue) << QJsonValue(stringValue); + QTest::newRow("stringList") << QVariant(stringList) << QJsonValue(jsonArray_string); + QTest::newRow("variantList") << QVariant(variantList) << QJsonValue(jsonArray_variant); + QTest::newRow("variantMap") << QVariant(variantMap) << QJsonValue(jsonObject); + QTest::newRow("variantHash") << QVariant(variantHash) << QJsonValue(jsonObject); +} - QVERIFY(QJsonValue::fromVariant(QVariant(QJsonValue(true))).isBool()); - QVERIFY(QJsonValue::fromVariant(QVariant(jsonArray_string)).isArray()); - QVERIFY(QJsonValue::fromVariant(QVariant(QJsonDocument(jsonArray_string))).isArray()); - QVERIFY(QJsonValue::fromVariant(QVariant(jsonObject)).isObject()); - QVERIFY(QJsonValue::fromVariant(QVariant(QJsonDocument(jsonObject))).isObject()); +void tst_QtJson::fromVariant() +{ + QFETCH( QVariant, variant ); + QFETCH( QJsonValue, jsonvalue ); + + QCOMPARE(QJsonValue::fromVariant(variant), jsonvalue); + QCOMPARE(variant.toJsonValue(), jsonvalue); +} + +void tst_QtJson::toVariant_data() +{ + fromVariant_data(); +} + +void tst_QtJson::toVariant() +{ + QFETCH( QVariant, variant ); + QFETCH( QJsonValue, jsonvalue ); + + QCOMPARE(jsonvalue.toVariant(), variant); } void tst_QtJson::fromVariantMap()