shard_den_json_extractor/
path.rs1use serde_json::Value;
4use shard_den_core::Result;
5
6#[derive(Debug, Clone)]
8pub enum JsonPath {
9 Key(String),
10 Index(usize),
11 Wildcard,
12 Recursive(String),
13}
14
15#[derive(Debug, Default)]
17pub struct PathParser;
18
19impl PathParser {
20 pub fn new() -> Self {
22 Self
23 }
24
25 #[doc(hidden)]
27 #[deprecated(since = "0.3.0", note = "Not yet implemented - use extract() instead")]
28 pub fn parse(&self, path: &str) -> Result<Vec<JsonPath>> {
29 let _ = path;
31 Ok(vec![])
32 }
33
34 #[doc(hidden)]
36 #[deprecated(since = "0.3.0", note = "Not yet implemented")]
37 pub fn traverse<'a>(&self, value: &'a Value, path: &[JsonPath]) -> Result<Vec<&'a Value>> {
38 let _ = path;
40 Ok(vec![value])
41 }
42
43 pub fn detect_paths(&self, value: &Value) -> Vec<String> {
45 let mut paths = Vec::new();
46 self.detect_paths_recursive(value, "", &mut paths);
47 paths
48 }
49
50 fn detect_paths_recursive(&self, value: &Value, prefix: &str, paths: &mut Vec<String>) {
51 match value {
52 Value::Object(map) => {
53 for (key, val) in map {
54 let path = if prefix.is_empty() {
55 format!("$.{}", key)
56 } else {
57 format!("{}.{}", prefix, key)
58 };
59 paths.push(path.clone());
60 self.detect_paths_recursive(val, &path, paths);
61 }
62 }
63 Value::Array(arr) => {
64 if arr.is_empty() {
65 return;
66 }
67 let path = format!("{}[*]", prefix);
69 paths.push(path);
70
71 if let Some(first) = arr.first() {
73 self.detect_paths_recursive(first, &format!("{}[*]", prefix), paths);
74 }
75 }
76 _ => {}
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84 use serde_json::json;
85
86 #[test]
87 fn test_path_parser_new() {
88 let parser = PathParser::new();
89 let _ = parser;
90 }
91
92 #[test]
93 fn test_detect_paths() {
94 let parser = PathParser::new();
95 let value = json!({
96 "name": "test",
97 "data": {
98 "items": [1, 2, 3]
99 }
100 });
101
102 let paths = parser.detect_paths(&value);
103 assert!(paths.contains(&"$.name".to_string()));
104 assert!(paths.contains(&"$.data".to_string()));
105 assert!(paths.contains(&"$.data.items[*]".to_string()));
106 }
107
108 #[test]
109 fn test_detect_paths_empty() {
110 let parser = PathParser::new();
111 let value = json!("simple string");
112 let paths = parser.detect_paths(&value);
113 assert!(paths.is_empty());
114 }
115
116 #[test]
117 fn test_detect_paths_array() {
118 let parser = PathParser::new();
119 let value = json!([1, 2, 3]);
120 let paths = parser.detect_paths(&value);
121 assert!(!paths.is_empty());
122 let has_array_path = paths.iter().any(|p| p.contains("[*]"));
127 assert!(
128 has_array_path,
129 "Expected path containing [*], got: {:?}",
130 paths
131 );
132 }
133
134 #[test]
135 fn test_detect_paths_nested() {
136 let parser = PathParser::new();
137 let value = json!({"a": {"b": {"c": 1}}});
138 let paths = parser.detect_paths(&value);
139 assert!(paths.contains(&"$.a".to_string()));
140 assert!(paths.contains(&"$.a.b".to_string()));
141 assert!(paths.contains(&"$.a.b.c".to_string()));
142 }
143
144 #[test]
145 fn test_detect_paths_number() {
146 let parser = PathParser::new();
147 let value = json!(42);
148 let paths = parser.detect_paths(&value);
149 assert!(paths.is_empty());
150 }
151
152 #[test]
153 fn test_detect_paths_bool() {
154 let parser = PathParser::new();
155 let value = json!(true);
156 let paths = parser.detect_paths(&value);
157 assert!(paths.is_empty());
158 }
159
160 #[test]
161 fn test_detect_paths_null() {
162 let parser = PathParser::new();
163 let value = json!(null);
164 let paths = parser.detect_paths(&value);
165 assert!(paths.is_empty());
166 }
167
168 #[test]
169 #[allow(deprecated)]
170 fn test_parse_deprecated() {
171 let parser = PathParser::new();
172 let result = parser.parse("data.items[0]");
173 assert!(result.is_ok());
175 assert!(result.unwrap().is_empty());
176 }
177
178 #[test]
179 #[allow(deprecated)]
180 fn test_traverse_deprecated() {
181 let parser = PathParser::new();
182 let value = json!({"key": "value"});
183 let result = parser.traverse(&value, &[]);
184 assert!(result.is_ok());
186 assert_eq!(result.unwrap().len(), 1);
187 }
188
189 #[test]
190 fn test_detect_paths_empty_array() {
191 let parser = PathParser::new();
192 let value = json!([]);
193 let paths = parser.detect_paths(&value);
194 assert!(paths.is_empty());
196 }
197
198 #[test]
199 fn test_detect_paths_complex_nested() {
200 let parser = PathParser::new();
201 let value = json!({
202 "users": [
203 {"name": "Alice", "age": 30},
204 {"name": "Bob", "age": 25}
205 ]
206 });
207 let paths = parser.detect_paths(&value);
208 assert!(paths.contains(&"$.users[*]".to_string()));
209 }
210}