1use super::serde_json::value::Index;
2use super::{IndexMap, Value, ValueType};
3
4#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct ValuePath<'a> {
7 pub value: &'a Value,
8 pub path: Vec<String>, }
10
11impl<'a> ValuePath<'a> {
12 pub fn new(value: &'a Value, path: Option<Vec<String>>) -> ValuePath<'a> {
28 let path = path.unwrap_or_default();
29 ValuePath { value, path }
30 }
31
32 pub fn jsonpath(&self) -> String {
34 let mut jsonpath = String::from("$");
35 for part in &self.path {
36 if part.starts_with('[') {
37 jsonpath.push_str(part);
38 } else {
39 jsonpath.push('.');
40 jsonpath.push_str(part);
41 }
42 }
43 jsonpath
44 }
45
46 pub fn index(&self, index: impl JSONPathIndex) -> ValuePath<'a> {
50 let mut child_path = self.path.to_vec();
51 child_path.push(index.jsonpath());
52 ValuePath {
53 value: &self.value[index],
54 path: child_path,
55 }
56 }
57
58 pub fn index_custom(
60 &self,
61 index: impl Index,
62 index_custom: impl JSONPathIndex,
63 ) -> ValuePath<'a> {
64 let mut child_path = self.path.to_vec();
65 child_path.push(index_custom.jsonpath());
66 ValuePath {
67 value: &self.value[index],
68 path: child_path,
69 }
70 }
71
72 fn value_paths(self, explode_array: bool, inspect_arrays: bool) -> Vec<ValuePath<'a>> {
75 let mut paths = Vec::new();
76
77 match self.value {
78 Value::Object(map) => {
79 for (k, _) in map {
80 let vp = self.index(k);
81 let inner_paths = vp.value_paths(explode_array, inspect_arrays);
82 paths.extend(inner_paths)
83 }
84 }
85 Value::Array(array) => {
86 if inspect_arrays {
87 for (i, _array_value) in array.iter().enumerate() {
88 let vp = self.index_custom(i, "[*]");
89 let inner_paths = vp.value_paths(explode_array, inspect_arrays);
90 paths.extend(inner_paths)
91 }
92 } else if explode_array {
93 for (i, _array_value) in array.iter().enumerate() {
94 let vp = self.index(i);
95 let inner_paths = vp.value_paths(explode_array, inspect_arrays);
96 paths.extend(inner_paths)
97 }
98 } else {
99 paths.push(self)
100 }
101 }
102 Value::Null | Value::Bool(_) | Value::Number(_) | Value::String(_) => paths.push(self),
103 }
104 paths
105 }
106}
107
108pub trait JSONPathIndex: Index {
109 fn jsonpath(&self) -> String;
110}
111
112impl JSONPathIndex for usize {
113 fn jsonpath(&self) -> String {
114 format!("[{}]", self)
115 }
116}
117
118impl JSONPathIndex for str {
119 fn jsonpath(&self) -> String {
120 self.to_string()
121 }
122}
123
124impl JSONPathIndex for String {
125 fn jsonpath(&self) -> String {
126 self.to_string()
127 }
128}
129
130impl<'a, T> JSONPathIndex for &'a T
131where
132 T: ?Sized + JSONPathIndex,
133{
134 fn jsonpath(&self) -> String {
135 (**self).jsonpath()
136 }
137}
138
139pub trait ValuePaths {
140 fn value_paths(&self, explode_array: bool, inspect_arrays: bool) -> Vec<ValuePath>;
141}
142
143impl ValuePaths for Value {
144 fn value_paths(&self, explode_array: bool, inspect_arrays: bool) -> Vec<ValuePath> {
151 let base_valuepath = ValuePath::new(self, None);
152 base_valuepath.value_paths(explode_array, inspect_arrays)
153 }
154}
155
156pub trait JSONPaths {
168 fn json_paths(&self, explode_array: bool, inspect_arrays: bool) -> Vec<String>;
171
172 fn json_paths_types(
175 &self,
176 explode_array: bool,
177 inspect_arrays: bool,
178 ) -> IndexMap<String, String>;
179}
180
181impl JSONPaths for Value {
182 fn json_paths(&self, explode_array: bool, inspect_arrays: bool) -> Vec<String> {
183 self.value_paths(explode_array, inspect_arrays)
184 .into_iter()
185 .map(|value_path| value_path.jsonpath())
186 .collect()
187 }
188
189 fn json_paths_types(
190 &self,
191 explode_array: bool,
192 inspect_arrays: bool,
193 ) -> IndexMap<String, String> {
194 self.value_paths(explode_array, inspect_arrays)
195 .into_iter()
196 .map(|value_path| (value_path.jsonpath(), value_path.value.value_type()))
197 .collect()
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204
205 use serde_json::json;
206
207 #[test]
208 fn basic_valuepath() {
209 let v = json!({"key1": "value1", "key2": {"subkey1": "value1"}});
210 let vp_0 = ValuePath::new(&v, None);
211 assert_eq!(vp_0.jsonpath(), "$".to_string());
212
213 let v_1 = &v["key2"];
214 let vp_1 = vp_0.index("key2");
215 assert_eq!(vp_1.value, v_1);
216 assert_eq!(vp_1.path, vec!["key2".to_string()]);
217 assert_eq!(vp_1.jsonpath(), "$.key2".to_string());
218 }
219
220 #[test]
221 fn basic_valuepath_array() {
222 let v = json!({"key1": "value1", "key2": ["a", "b"]});
223 let vp_0 = ValuePath::new(&v, None);
224
225 let v_2 = &v["key2"][0];
226 let vp_1 = vp_0.index("key2");
227 let vp_2 = vp_1.index(0);
228
229 assert_eq!(vp_2.value, v_2);
230 assert_eq!(vp_2.path, vec!["key2".to_string(), "[0]".to_string()]);
231 assert_eq!(vp_1.jsonpath(), "$.key2".to_string());
232 assert_eq!(vp_2.jsonpath(), "$.key2[0]".to_string())
233 }
234
235 #[test]
236 fn parse_valuepaths() {
237 let v = json!({"key1": "value1", "key2": ["a", "b"]});
238 let vps = v.value_paths(false, false);
239
240 let vp_0 = ValuePath::new(&v, None);
241 let vp_1 = ValuePath::new(&v["key1"], Some(vec!["key1".to_string()]));
242 let vp_2 = ValuePath::new(&v["key2"], Some(vec!["key2".to_string()]));
243 let vp_1_alt = vp_0.index("key1");
244 let vp_2_alt = vp_0.index("key2");
245
246 let expected = vec![vp_1, vp_2];
247 let expected_alt = vec![vp_1_alt, vp_2_alt];
248
249 assert_eq!(vps, expected);
250 assert_eq!(vps, expected_alt);
251 assert_eq!(v.value_paths(false, false), expected);
252 assert_eq!(v.value_paths(false, false), expected_alt);
253 }
254
255 #[test]
256 fn parse_valuepaths_explode_array() {
257 let v = json!({"key1": "value1", "key2": ["a", "b"]});
258 let vps = v.value_paths(true, false);
259
260 let vp_0 = ValuePath::new(&v, None);
261 let vp_1 = ValuePath::new(&v["key1"], Some(vec!["key1".to_string()]));
262 let vp_2_1 = ValuePath::new(
263 &v["key2"][0],
264 Some(vec!["key2".to_string(), "[0]".to_string()]),
265 );
266 let vp_2_2 = ValuePath::new(
267 &v["key2"][1],
268 Some(vec!["key2".to_string(), "[1]".to_string()]),
269 );
270 let vp_1_alt = vp_0.index("key1");
271 let vp_2_1_alt = vp_0.index("key2").index(0);
272 let vp_2_2_alt = vp_0.index("key2").index(1);
273
274 assert_eq!(vps, vec![vp_1, vp_2_1, vp_2_2]);
275 assert_eq!(vps, vec![vp_1_alt, vp_2_1_alt, vp_2_2_alt]);
276 }
277
278 #[test]
279 fn parse_valuepaths_inspect_array() {
280 let v = json!({"key1": "value1", "key2": ["a", "b"]});
281 let vps = v.value_paths(false, true);
282
283 let vp_1 = ValuePath::new(&v["key1"], Some(vec!["key1".to_string()]));
284 let vp_2_1 = ValuePath::new(
285 &v["key2"][0],
286 Some(vec!["key2".to_string(), "[*]".to_string()]),
287 );
288 let vp_2_2 = ValuePath::new(
289 &v["key2"][1],
290 Some(vec!["key2".to_string(), "[*]".to_string()]),
291 );
292
293 assert_eq!(vps, vec![vp_1, vp_2_1, vp_2_2]);
294 }
295
296 #[test]
297 fn typical_parse_json_paths() {
298 let v = json!({"key1": "value1", "key2": {"subkey1": "value1"}});
299 let out_expected = vec![String::from("$.key1"), String::from("$.key2.subkey1")];
300 assert_eq!(v.json_paths(false, false), out_expected);
301 }
302
303 #[test]
304 fn trivial_parse_json_paths() {
305 let v = json!(1);
306 let out_expected = vec![String::from("$")];
307 assert_eq!(v.json_paths(false, false), out_expected);
308 }
309
310 #[test]
311 fn typical_parse_json_paths_types() {
312 let v = json!({"key1": "value1", "key2": {"subkey1": ["value1"]}});
313 let mut out_expected = IndexMap::new();
314 out_expected.insert("$.key1".to_string(), "String".to_string());
315 out_expected.insert("$.key2.subkey1".to_string(), "Array".to_string());
316 assert_eq!(v.json_paths_types(false, false), out_expected);
317 }
318
319 #[test]
320 fn trivial_parse_json_paths_types() {
321 let v = json!(1);
322 let mut out_expected = IndexMap::new();
323 out_expected.insert("$".to_string(), "Number".to_string());
324 assert_eq!(v.json_paths_types(false, false), out_expected);
325 }
326}