pub fn values_structurally_equal(a: &serde_json::Value, b: &serde_json::Value) -> bool {
use serde_json::Value;
match (a, b) {
(Value::Null, Value::Null) => true,
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::Number(a), Value::Number(b)) => {
if let (Some(a), Some(b)) = (a.as_f64(), b.as_f64()) {
(a - b).abs() < f64::EPSILON
} else {
a == b
}
}
(Value::String(a), Value::String(b)) => a == b,
(Value::Array(a), Value::Array(b)) => {
a.len() == b.len()
&& a.iter()
.zip(b.iter())
.all(|(a, b)| values_structurally_equal(a, b))
}
(Value::Object(a), Value::Object(b)) => {
for (key, val_b) in b {
match a.get(key) {
Some(val_a) => {
if !values_structurally_equal(val_a, val_b) {
return false;
}
}
None => {
if !val_b.is_null() {
return false;
}
}
}
}
for (key, val_a) in a {
if !b.contains_key(key) && !val_a.is_null() {
return false;
}
}
true
}
_ => false,
}
}