diff --git a/src/corelib/compat/removed_api.cpp b/src/corelib/compat/removed_api.cpp index c88fb046bc..c02ebd3814 100644 --- a/src/corelib/compat/removed_api.cpp +++ b/src/corelib/compat/removed_api.cpp @@ -978,6 +978,19 @@ bool QJsonDocument::operator==(const QJsonDocument &other) const return comparesEqual(*this, other); } +#include "qjsonobject.h" + +bool QJsonObject::operator==(const QJsonObject &other) const +{ + return comparesEqual(*this, other); +} + + +bool QJsonObject::operator!=(const QJsonObject &other) const +{ + return !comparesEqual(*this, other); +} + #include "qjsonvalue.h" bool QJsonValue::operator==(const QJsonValue &other) const diff --git a/src/corelib/serialization/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index fb81599e33..2fbac931dc 100644 --- a/src/corelib/serialization/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp @@ -31,6 +31,10 @@ QT_BEGIN_NAMESPACE \brief The QJsonObject class encapsulates a JSON object. + \compares equality + \compareswith equality QJsonValue + \endcompareswith + A JSON object is a list of key value pairs, where the keys are unique strings and the values are represented by a QJsonValue. @@ -613,22 +617,24 @@ bool QJsonObject::containsImpl(T key) const } /*! - Returns \c true if \a other is equal to this object. - */ -bool QJsonObject::operator==(const QJsonObject &other) const + \fn bool QJsonObject::operator==(const QJsonObject &lhs, const QJsonObject &rhs) + + Returns \c true if \a lhs object is equal to \a rhs, \c false otherwise. +*/ +bool comparesEqual(const QJsonObject &lhs, const QJsonObject &rhs) noexcept { - if (o == other.o) + if (lhs.o == rhs.o) return true; - if (!o) - return !other.o->elements.size(); - if (!other.o) - return !o->elements.size(); - if (o->elements.size() != other.o->elements.size()) + if (!lhs.o) + return !rhs.o->elements.size(); + if (!rhs.o) + return !lhs.o->elements.size(); + if (lhs.o->elements.size() != rhs.o->elements.size()) return false; - for (qsizetype i = 0, end = o->elements.size(); i < end; ++i) { - if (o->valueAt(i) != other.o->valueAt(i)) + for (qsizetype i = 0, end = lhs.o->elements.size(); i < end; ++i) { + if (lhs.o->valueAt(i) != rhs.o->valueAt(i)) return false; } @@ -636,12 +642,10 @@ bool QJsonObject::operator==(const QJsonObject &other) const } /*! - Returns \c true if \a other is not equal to this object. - */ -bool QJsonObject::operator!=(const QJsonObject &other) const -{ - return !(*this == other); -} + \fn bool QJsonObject::operator!=(const QJsonObject &lhs, const QJsonObject &rhs) + + Returns \c true if \a lhs object is not equal to \a rhs, \c false otherwise. +*/ /*! Removes the (key, value) pair pointed to by the iterator \a it diff --git a/src/corelib/serialization/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 64967d4a0e..bdf35a4f20 100644 --- a/src/corelib/serialization/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h @@ -72,9 +72,10 @@ public: bool contains(QStringView key) const; bool contains(QLatin1StringView key) const; +#if QT_CORE_REMOVED_SINCE(6, 8) bool operator==(const QJsonObject &other) const; bool operator!=(const QJsonObject &other) const; - +#endif class const_iterator; class iterator @@ -236,6 +237,15 @@ public: inline bool empty() const { return isEmpty(); } private: + friend Q_CORE_EXPORT bool comparesEqual(const QJsonObject &lhs, + const QJsonObject &rhs) noexcept; + friend bool comparesEqual(const QJsonObject &lhs, + const QJsonValue &rhs) noexcept + { + return comparesEqual(lhs, rhs.toObject()); + } + Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject) + Q_DECLARE_EQUALITY_COMPARABLE(QJsonObject, QJsonValue) friend class QJsonValue; friend class QJsonDocument; friend class QJsonPrivate::Value; diff --git a/tests/auto/corelib/serialization/json/tst_qtjson.cpp b/tests/auto/corelib/serialization/json/tst_qtjson.cpp index 3705084d26..2f3e8e07d5 100644 --- a/tests/auto/corelib/serialization/json/tst_qtjson.cpp +++ b/tests/auto/corelib/serialization/json/tst_qtjson.cpp @@ -177,10 +177,12 @@ void tst_QtJson::compareCompiles() { QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); + QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); + QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); QTestPrivate::testEqualityOperatorsCompile(); @@ -823,9 +825,12 @@ void tst_QtJson::testObjectNested() QJsonValue v = inner; QCOMPARE(v.toObject(), inner); QCOMPARE(v.toObject(otherObject), inner); + QT_TEST_EQUALITY_OPS(v.toObject(), inner, true); + QT_TEST_EQUALITY_OPS(v.toObject(otherObject), inner, true); inner.insert("number", 999.); outer.insert("nested", inner); + QT_TEST_EQUALITY_OPS(outer, inner, false); // if we don't modify the original JsonObject, value() // should return the same object (non-detached). @@ -835,6 +840,8 @@ void tst_QtJson::testObjectNested() QCOMPARE(value.value("number").toDouble(), 999.); QCOMPARE(v.toObject(), inner); QCOMPARE(v.toObject(otherObject), inner); + QT_TEST_EQUALITY_OPS(v.toObject(), inner, true); + QT_TEST_EQUALITY_OPS(v.toObject(otherObject), inner, true); QCOMPARE(v["number"].toDouble(), 999.); // if we modify the original object, it should detach and not @@ -860,6 +867,7 @@ void tst_QtJson::testObjectNested() QCOMPARE(outer.value("nested").toObject().value("nested").toObject(), twoDeep); QCOMPARE(outer.value("nested").toObject().value("nested").toObject().value("boolean").toBool(), true); + QT_TEST_EQUALITY_OPS(outer.value("nested").toObject().value("nested").toObject(), twoDeep, true); } void tst_QtJson::testArrayNested() @@ -885,6 +893,7 @@ void tst_QtJson::testArrayNested() object.insert("boolean", true); outer.append(object); QCOMPARE(outer.last().toObject(), object); + QT_TEST_EQUALITY_OPS(outer.last().toObject(), object, true); QCOMPARE(outer.last().toObject().value("boolean").toBool(), true); // two deep arrays @@ -925,6 +934,7 @@ void tst_QtJson::testObjectNestedEmpty() QT_TEST_EQUALITY_OPS(QJsonDocument(), QJsonDocument(value), false); QCOMPARE(value.size(), 0); QCOMPARE(value, inner); + QT_TEST_EQUALITY_OPS(value, inner, true); QCOMPARE(value.size(), 0); object.insert("count", 0.); QCOMPARE(object.value("inner").toObject().size(), 0); @@ -1096,6 +1106,7 @@ void tst_QtJson::testObjectIteration() { QJsonObject object2 = object; QCOMPARE(object, object2); + QT_TEST_EQUALITY_OPS(object, object2, true); QJsonValue val = *object2.begin(); auto next = object2.erase(object2.begin()); @@ -1116,6 +1127,7 @@ void tst_QtJson::testObjectIteration() { QJsonObject object2 = object; QCOMPARE(object, object2); + QT_TEST_EQUALITY_OPS(object, object2, true); QJsonValue val = *(object2.end() - 1); auto next = object2.erase(object2.end() - 1); @@ -1135,6 +1147,7 @@ void tst_QtJson::testObjectIteration() { QJsonObject object2 = object; QCOMPARE(object, object2); + QT_TEST_EQUALITY_OPS(object, object2, true); QJsonObject::iterator it = object2.find(QString::number(5)); QJsonValue val = *it; @@ -2559,6 +2572,13 @@ void tst_QtJson::testCompaction() } QCOMPARE(obj.size(), 1); QCOMPARE(obj.value(QLatin1String("foo")).toString(), QLatin1String("bar")); + + QJsonObject obj2; + + QT_TEST_EQUALITY_OPS(obj, obj2, false); + QT_TEST_EQUALITY_OPS(QJsonObject(), obj2, true); + obj2 = obj; + QT_TEST_EQUALITY_OPS(obj, obj2, true); } void tst_QtJson::testDebugStream() @@ -2883,7 +2903,7 @@ void tst_QtJson::valueEquals() QCOMPARE(QJsonValue(QJsonObject()), QJsonValue(QJsonObject())); QJsonObject nonEmptyObject; nonEmptyObject.insert("Key", true); - QVERIFY(QJsonValue(QJsonObject()) != nonEmptyObject); + QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), nonEmptyObject, false); QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(QJsonValue::Undefined), false); QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(), false); QT_TEST_EQUALITY_OPS(QJsonValue(QJsonObject()), QJsonValue(true), false);