diff --git a/include/envoy/json/json_object.h b/include/envoy/json/json_object.h index a5161ccfa91b8..7df162540ff58 100644 --- a/include/envoy/json/json_object.h +++ b/include/envoy/json/json_object.h @@ -147,8 +147,13 @@ class Object { virtual double getDouble(const std::string& name, double default_value) const PURE; /** - * @return a hash of the JSON object. This is a hash of each nested element in stable order. - * It does not consider white space that was originally in the parsed JSON. + * @return a hash of the JSON object. + * Per RFC 7159: + * An object is an unordered collection of zero or more name/value + * pairs, where a name is a string and a value is a string, number, + * boolean, null, object, or array. + * Objects with fields in different orders are equivalent and produce the same hash. + * It does not consider white space that was originally in the parsed JSON. */ virtual uint64_t hash() const PURE; diff --git a/source/common/json/json_loader.cc b/source/common/json/json_loader.cc index 0e3a084b5d7c0..083f7b64f4091 100644 --- a/source/common/json/json_loader.cc +++ b/source/common/json/json_loader.cc @@ -3,10 +3,10 @@ #include #include #include +#include #include #include #include -#include #include #include "common/common/assert.h" @@ -127,7 +127,7 @@ class Field : public Object { bool boolean_value_; double double_value_; int64_t integer_value_; - std::unordered_map object_value_; + std::map object_value_; std::string string_value_; }; diff --git a/test/common/json/json_loader_test.cc b/test/common/json/json_loader_test.cc index 47c4094f7969c..1201a3668d104 100644 --- a/test/common/json/json_loader_test.cc +++ b/test/common/json/json_loader_test.cc @@ -246,8 +246,14 @@ TEST_F(JsonLoaderTest, Hash) { ObjectSharedPtr json1 = Factory::loadFromString("{\"value1\": 10.5, \"value2\": -12.3}"); ObjectSharedPtr json2 = Factory::loadFromString("{\"value2\": -12.3, \"value1\": 10.5}"); ObjectSharedPtr json3 = Factory::loadFromString(" { \"value2\": -12.3, \"value1\": 10.5} "); - EXPECT_NE(json1->hash(), json2->hash()); + ObjectSharedPtr json4 = Factory::loadFromString("{\"value1\": 10.5}"); + + // Objects with keys in different orders should be the same + EXPECT_EQ(json1->hash(), json2->hash()); + // Whitespace is ignored EXPECT_EQ(json2->hash(), json3->hash()); + // Ensure different hash is computed for different objects + EXPECT_NE(json1->hash(), json4->hash()); } TEST_F(JsonLoaderTest, Schema) {