#[cfg(feature = "json")]
use serde_json::Value;
#[cfg(feature = "json")]
pub fn is_string(val: &Value) -> bool {
val.is_string()
}
#[cfg(feature = "json")]
pub fn is_number(val: &Value) -> bool {
val.is_number()
}
#[cfg(feature = "json")]
pub fn is_bool(val: &Value) -> bool {
val.is_boolean()
}
#[cfg(feature = "json")]
pub fn is_array(val: &Value) -> bool {
val.is_array()
}
#[cfg(feature = "json")]
pub fn is_object(val: &Value) -> bool {
val.is_object()
}
#[cfg(feature = "json")]
pub fn is_null(val: &Value) -> bool {
val.is_null()
}
#[cfg(feature = "json")]
pub fn is_defined(val: &Value) -> bool {
!val.is_null()
}
#[cfg(feature = "json")]
pub fn deep_equal(a: &Value, b: &Value) -> bool {
match (a, b) {
(Value::Null, Value::Null) => true,
(Value::Bool(a), Value::Bool(b)) => a == b,
(Value::Number(a), Value::Number(b)) => 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(|(x, y)| deep_equal(x, y))
}
(Value::Object(a), Value::Object(b)) => {
a.len() == b.len()
&& a.iter()
.all(|(k, v)| b.get(k).map(|bv| deep_equal(v, bv)).unwrap_or(false))
}
_ => false,
}
}
#[cfg(feature = "json")]
pub fn get_path<'a>(val: &'a Value, path: &str) -> Option<&'a Value> {
let mut current: Option<&'a Value> = Some(val);
for key in path.split('.') {
current = current.and_then(|v| {
if let Some(obj) = v.as_object() {
obj.get(key)
} else if let Some(arr) = v.as_array() {
key.parse::<usize>().ok().and_then(|i| arr.get(i))
} else {
None
}
});
}
current
}
#[cfg(feature = "json")]
pub fn set_path(val: Value, path: &str, new: Value) -> Value {
let keys: Vec<&str> = path.split('.').collect();
if keys.is_empty() {
return new;
}
let mut result = val;
if let Some(_last) = keys.last() {
for key in &keys[..keys.len() - 1] {
if result.get(*key).is_none() {
if let Ok(idx) = key.parse::<usize>() {
while result.as_array().map(|a| a.len()).unwrap_or(0) <= idx {
result = Value::Array(vec![result, Value::Null]);
}
} else {
result = Value::Object(serde_json::Map::new());
}
}
}
}
if let Value::Object(ref mut obj) = result {
if let Some(last_key) = keys.last() {
obj.insert(last_key.to_string(), new);
}
}
result
}
#[cfg(feature = "json")]
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_is_string() {
assert!(is_string(&json!("hello")));
assert!(!is_string(&json!(42)));
}
#[test]
fn test_is_number() {
assert!(is_number(&json!(42)));
assert!(!is_number(&json!("hello")));
}
#[test]
fn test_is_bool() {
assert!(is_bool(&json!(true)));
assert!(!is_bool(&json!(42)));
}
#[test]
fn test_is_array() {
assert!(is_array(&json!([1, 2, 3])));
assert!(!is_array(&json!(42)));
}
#[test]
fn test_is_object() {
assert!(is_object(&json!({"a": 1})));
assert!(!is_object(&json!([1, 2])));
}
#[test]
fn test_is_null() {
assert!(is_null(&json!(null)));
assert!(!is_null(&json!(42)));
}
#[test]
fn test_deep_equal() {
assert!(deep_equal(&json!({"a": 1}), &json!({"a": 1})));
assert!(!deep_equal(&json!({"a": 1}), &json!({"a": 2})));
}
#[test]
fn test_get_path() {
let val = json!({"user": {"address": {"city": "NYC"}}});
assert_eq!(get_path(&val, "user.address.city"), Some(&json!("NYC")));
}
#[test]
fn test_set_path() {
let val = json!({"a": 1});
let result = set_path(val, "b", json!(2));
assert_eq!(result.get("b"), Some(&json!(2)));
}
}