From 22c4b4b9389cefbd264ff89bf3b3a4c74776898c Mon Sep 17 00:00:00 2001 From: Gin890 <79114795+Gin890@users.noreply.github.com> Date: Sun, 11 Oct 2026 23:16:05 +0000 Subject: [PATCH] Json: implement structural == for JsonObject/JsonValue/JsonArray. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the TODO in JsonObject.h where operator== compared dump() strings (two full JSON serializations and string allocations per compare). The new operators compare types and contents recursively: - JsonValue: type-strict, then primitive/pointer payload compare. - JsonArray: size, then element-wise. - JsonObject: size, then key/value pairs (std::map iteration order). Semantics match the old dump-based == for all well-formed values (int 1 != 1.0, key order irrelevant), with one deliberate fix: null != {} — the old compare treated them as equal because to_nlohmann() serializes an empty object as null (pre-existing dump bug, tracked separately). --- Common/Cpp/Json/JsonArray.h | 18 ++++++++++++++++++ Common/Cpp/Json/JsonObject.h | 14 ++++++++++++-- Common/Cpp/Json/JsonValue.cpp | 30 ++++++++++++++++++++++++++++++ Common/Cpp/Json/JsonValue.h | 5 +++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/Common/Cpp/Json/JsonArray.h b/Common/Cpp/Json/JsonArray.h index 42bf70d4a3..8165e12e35 100644 --- a/Common/Cpp/Json/JsonArray.h +++ b/Common/Cpp/Json/JsonArray.h @@ -26,6 +26,24 @@ class JsonArray{ public: JsonArray clone() const; + // Structurally compare two arrays. + friend bool operator==(const JsonArray& x, const JsonArray& y){ + if (x.m_data.size() != y.m_data.size()){ + return false; + } + auto itx = x.m_data.cbegin(); + auto ity = y.m_data.cbegin(); + for (; itx != x.m_data.cend(); ++itx, ++ity){ + if (!(*itx == *ity)){ + return false; + } + } + return true; + } + friend bool operator!=(const JsonArray& x, const JsonArray& y){ + return !(x == y); + } + public: std::string dump(int indent = 4) const; void dump(const std::string& filename, int indent = 4) const; diff --git a/Common/Cpp/Json/JsonObject.h b/Common/Cpp/Json/JsonObject.h index c6f817b04f..421c702bbd 100644 --- a/Common/Cpp/Json/JsonObject.h +++ b/Common/Cpp/Json/JsonObject.h @@ -19,9 +19,19 @@ class JsonObject{ JsonObject(JsonObject&& x) = default; JsonObject& operator=(JsonObject&& x) = default; - // TODO: implement == properly. For JsonValue as well. + // Structurally compare two objects. friend bool operator==(const JsonObject& x, const JsonObject& y){ - return x.dump() == y.dump(); + if (x.m_data.size() != y.m_data.size()){ + return false; + } + auto itx = x.m_data.cbegin(); + auto ity = y.m_data.cbegin(); + for (; itx != x.m_data.cend(); ++itx, ++ity){ + if (itx->first != ity->first || !(itx->second == ity->second)){ + return false; + } + } + return true; } friend bool operator!=(const JsonObject& x, const JsonObject& y){ return !(x == y); diff --git a/Common/Cpp/Json/JsonValue.cpp b/Common/Cpp/Json/JsonValue.cpp index bf244f4894..d7d99df846 100644 --- a/Common/Cpp/Json/JsonValue.cpp +++ b/Common/Cpp/Json/JsonValue.cpp @@ -367,6 +367,36 @@ bool JsonValue::read_string(std::string& value) const{ +// Equality. + +bool operator==(const JsonValue& x, const JsonValue& y){ + if (x.m_type != y.m_type){ + return false; + } + switch (x.m_type){ + case JsonType::EMPTY: + return true; + case JsonType::BOOLEAN: + return x.u.m_bool == y.u.m_bool; + case JsonType::INTEGER: + return x.u.m_integer == y.u.m_integer; + case JsonType::FLOAT: + return x.u.m_float == y.u.m_float; + case JsonType::STRING: + return *x.u.m_string == *y.u.m_string; + case JsonType::ARRAY: + return *x.u.m_array == *y.u.m_array; + case JsonType::OBJECT: + return *x.u.m_object == *y.u.m_object; + } + return false; +} +bool operator!=(const JsonValue& x, const JsonValue& y){ + return !(x == y); +} + + + JsonValue parse_json(const std::string& str){ return from_nlohmann(nlohmann::json::parse(str, nullptr, false)); } diff --git a/Common/Cpp/Json/JsonValue.h b/Common/Cpp/Json/JsonValue.h index 09eb5621bc..0ad4d1efe3 100644 --- a/Common/Cpp/Json/JsonValue.h +++ b/Common/Cpp/Json/JsonValue.h @@ -72,6 +72,11 @@ class JsonValue{ public: JsonValue clone() const; + // Structurally compare two values. + // (Defined in JsonValue.cpp; requires the complete types of JsonArray/JsonObject.) + friend bool operator==(const JsonValue& x, const JsonValue& y); + friend bool operator!=(const JsonValue& x, const JsonValue& y); + public: JsonValue() = default; JsonValue(bool x);