1#[cfg(feature = "json")]
9use serde_json::Value;
10
11#[cfg(feature = "json")]
12pub fn is_string(val: &Value) -> bool {
13 val.is_string()
14}
15
16#[cfg(feature = "json")]
17pub fn is_number(val: &Value) -> bool {
18 val.is_number()
19}
20
21#[cfg(feature = "json")]
22pub fn is_bool(val: &Value) -> bool {
23 val.is_boolean()
24}
25
26#[cfg(feature = "json")]
27pub fn is_array(val: &Value) -> bool {
28 val.is_array()
29}
30
31#[cfg(feature = "json")]
32pub fn is_object(val: &Value) -> bool {
33 val.is_object()
34}
35
36#[cfg(feature = "json")]
37pub fn is_null(val: &Value) -> bool {
38 val.is_null()
39}
40
41#[cfg(feature = "json")]
42pub fn is_defined(val: &Value) -> bool {
43 !val.is_null()
44}
45
46#[cfg(feature = "json")]
47pub fn deep_equal(a: &Value, b: &Value) -> bool {
48 match (a, b) {
49 (Value::Null, Value::Null) => true,
50 (Value::Bool(a), Value::Bool(b)) => a == b,
51 (Value::Number(a), Value::Number(b)) => a == b,
52 (Value::String(a), Value::String(b)) => a == b,
53 (Value::Array(a), Value::Array(b)) => {
54 a.len() == b.len() && a.iter().zip(b.iter()).all(|(x, y)| deep_equal(x, y))
55 }
56 (Value::Object(a), Value::Object(b)) => {
57 a.len() == b.len()
58 && a.iter()
59 .all(|(k, v)| b.get(k).map(|bv| deep_equal(v, bv)).unwrap_or(false))
60 }
61 _ => false,
62 }
63}
64
65#[cfg(feature = "json")]
66pub fn get_path<'a>(val: &'a Value, path: &str) -> Option<&'a Value> {
67 let mut current: Option<&'a Value> = Some(val);
68 for key in path.split('.') {
69 current = current.and_then(|v| {
70 if let Some(obj) = v.as_object() {
71 obj.get(key)
72 } else if let Some(arr) = v.as_array() {
73 key.parse::<usize>().ok().and_then(|i| arr.get(i))
74 } else {
75 None
76 }
77 });
78 }
79 current
80}
81
82#[cfg(feature = "json")]
83pub fn set_path(val: Value, path: &str, new: Value) -> Value {
84 let keys: Vec<&str> = path.split('.').collect();
85 if keys.is_empty() {
86 return new;
87 }
88
89 let mut result = val;
90 if let Some(_last) = keys.last() {
91 for key in &keys[..keys.len() - 1] {
92 if result.get(*key).is_none() {
93 if let Ok(idx) = key.parse::<usize>() {
94 while result.as_array().map(|a| a.len()).unwrap_or(0) <= idx {
95 result = Value::Array(vec![result, Value::Null]);
96 }
97 } else {
98 result = Value::Object(serde_json::Map::new());
99 }
100 }
101 }
102 }
103
104 if let Value::Object(ref mut obj) = result {
105 if let Some(last_key) = keys.last() {
106 obj.insert(last_key.to_string(), new);
107 }
108 }
109 result
110}
111
112#[cfg(feature = "json")]
113#[cfg(test)]
114mod tests {
115 use super::*;
116 use serde_json::json;
117
118 #[test]
119 fn test_is_string() {
120 assert!(is_string(&json!("hello")));
121 assert!(!is_string(&json!(42)));
122 }
123
124 #[test]
125 fn test_is_number() {
126 assert!(is_number(&json!(42)));
127 assert!(!is_number(&json!("hello")));
128 }
129
130 #[test]
131 fn test_is_bool() {
132 assert!(is_bool(&json!(true)));
133 assert!(!is_bool(&json!(42)));
134 }
135
136 #[test]
137 fn test_is_array() {
138 assert!(is_array(&json!([1, 2, 3])));
139 assert!(!is_array(&json!(42)));
140 }
141
142 #[test]
143 fn test_is_object() {
144 assert!(is_object(&json!({"a": 1})));
145 assert!(!is_object(&json!([1, 2])));
146 }
147
148 #[test]
149 fn test_is_null() {
150 assert!(is_null(&json!(null)));
151 assert!(!is_null(&json!(42)));
152 }
153
154 #[test]
155 fn test_deep_equal() {
156 assert!(deep_equal(&json!({"a": 1}), &json!({"a": 1})));
157 assert!(!deep_equal(&json!({"a": 1}), &json!({"a": 2})));
158 }
159
160 #[test]
161 fn test_get_path() {
162 let val = json!({"user": {"address": {"city": "NYC"}}});
163 assert_eq!(get_path(&val, "user.address.city"), Some(&json!("NYC")));
164 }
165
166 #[test]
167 fn test_set_path() {
168 let val = json!({"a": 1});
169 let result = set_path(val, "b", json!(2));
170 assert_eq!(result.get("b"), Some(&json!(2)));
171 }
172}