json_value_search/lib.rs
1extern crate serde_json;
2
3use regex::Regex;
4use serde_json::Value;
5use std::collections::HashMap;
6use std::io;
7use std::sync::Mutex;
8
9use lazy_static::lazy_static;
10
11lazy_static! {
12 static ref RE_CACHE: Mutex<HashMap<String, Regex>> = Mutex::new(HashMap::new());
13}
14
15fn get_or_create_regex(pattern: &str) -> io::Result<Regex> {
16 let mut cache = RE_CACHE.lock().unwrap();
17
18 if let Some(re) = cache.get(pattern) {
19 return Ok(re.clone());
20 }
21
22 let re = Regex::new(pattern).map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
23 cache.insert(pattern.to_string(), re.clone());
24
25 Ok(re)
26}
27
28/// Trait used to search elements into Json Value
29pub trait Search {
30 /// Search elements by path
31 fn search(self, path: &str) -> io::Result<Option<Value>>;
32 /// Search elements by a list of fields.
33 fn search_by_fields(&self, fields: &[&str]) -> io::Result<Option<Value>>;
34}
35
36impl Search for serde_json::Value {
37 /// # Examples: Find elements in an object.
38 /// ```
39 /// use json_value_search::Search;
40 /// use serde_json::Value;
41 ///
42 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
43 ///
44 /// let value_expected_with_wildcard: Value = serde_json::from_str(r#"[{"field.B":"value_B"},{"field_C":"value_C"}]"#).unwrap();
45 /// assert_eq!(Some(value_expected_with_wildcard),value.clone().search(r#"/field_A/*"#).unwrap());
46 ///
47 /// let value_expected_for_specific_field: Value = serde_json::from_str(r#"["value_B"]"#).unwrap();
48 /// assert_eq!(Some(value_expected_for_specific_field),value.clone().search(r#"/field_A/*/field.B"#).unwrap());
49 ///
50 /// let value_expected_for_specific_index: Value = serde_json::from_str(r#"{"field.B":"value_B"}"#).unwrap();
51 /// assert_eq!(Some(value_expected_for_specific_index),value.clone().search(r#"/field_A/0"#).unwrap());
52 ///
53 /// let value_expected_with_regex: Value = serde_json::from_str(r#"["value_B","value_C"]"#).unwrap();
54 /// assert_eq!(Some(value_expected_with_regex),value.clone().search(r#"/field_A/*/field.+"#).unwrap());
55 /// ```
56 /// # Examples: Find the same elements in an object or array return the same value.
57 /// ```
58 /// use json_value_search::Search;
59 /// use serde_json::Value;
60 ///
61 /// let value1: Value = serde_json::from_str(r#"[{"array1":[{"field1":"value1"},{"field2":"value2"}]}]"#).unwrap();
62 /// let value2: Value = serde_json::from_str(r#"{"array2":[{"field1":"value1"},{"field2":"value2"}]}"#).unwrap();
63 ///
64 /// let result1 = value1.search(r#"/*/array*/*"#).unwrap();
65 /// let result2 = value2.search(r#"/array*/*"#).unwrap();
66 /// assert_eq!(result1, result2);
67 /// ```
68 /// # Examples: Not found an element return None.
69 /// ```
70 /// use json_value_search::Search;
71 /// use serde_json::Value;
72 ///
73 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
74 ///
75 /// let result = value.clone().search(r#"/not_found/*"#);
76 /// match result {
77 /// Ok(None) => (),
78 /// Ok(Some(_)) => panic!("Should return None"),
79 /// Err(e) => panic!(format!("Should not be in error, {}", e))
80 /// };
81 /// ```
82 /// # Examples: Write a bad regex return an error.
83 /// ```
84 /// use json_value_search::Search;
85 /// use serde_json::Value;
86 ///
87 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
88 ///
89 /// let result = value.clone().search(r#"/["#);
90 /// match result {
91 /// Ok(_) => panic!("Should return an error"),
92 /// Err(e) => ()
93 /// };
94 /// ```
95 fn search(self, path: &str) -> io::Result<Option<Value>> {
96 let fields: Vec<&str> = path.split("/").skip(1).collect();
97
98 match self {
99 Value::Array(_) | Value::Object(_) => self.search_by_fields(&fields),
100 _ => Ok(None),
101 }
102 }
103 /// # Examples: Find elements in an object.
104 /// ```
105 /// use json_value_search::Search;
106 /// use serde_json::Value;
107 ///
108 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
109 ///
110 /// let value_expected_with_wildcard: Value = serde_json::from_str(r#"[{"field.B":"value_B"},{"field_C":"value_C"}]"#).unwrap();
111 /// assert_eq!(Some(value_expected_with_wildcard),value.clone().search_by_fields(&vec!["field_A","*"]).unwrap());
112 ///
113 /// let value_expected_for_specific_field: Value = serde_json::from_str(r#"["value_B"]"#).unwrap();
114 /// assert_eq!(Some(value_expected_for_specific_field),value.clone().search_by_fields(&vec!["field_A","*","field.B"]).unwrap());
115 ///
116 /// let value_expected_for_specific_index: Value = serde_json::from_str(r#"{"field.B":"value_B"}"#).unwrap();
117 /// assert_eq!(Some(value_expected_for_specific_index),value.clone().search_by_fields(&vec!["field_A","0"]).unwrap());
118 ///
119 /// let value_expected_with_regex: Value = serde_json::from_str(r#"["value_B","value_C"]"#).unwrap();
120 /// assert_eq!(Some(value_expected_with_regex),value.clone().search_by_fields(&vec!["field_A","*","field.+"]).unwrap());
121 /// ```
122 /// # Examples: Find the same elements in an object or array return the same value.
123 /// ```
124 /// use json_value_search::Search;
125 /// use serde_json::Value;
126 ///
127 /// let value1: Value = serde_json::from_str(r#"[{"array1":[{"field1":"value1"},{"field2":"value2"}]}]"#).unwrap();
128 /// let value2: Value = serde_json::from_str(r#"{"array2":[{"field1":"value1"},{"field2":"value2"}]}"#).unwrap();
129 ///
130 /// let result1 = value1.search_by_fields(&vec!["*","array*","*"]).unwrap();
131 /// let result2 = value2.search_by_fields(&vec!["array*","*"]).unwrap();
132 /// assert_eq!(result1, result2);
133 /// ```
134 /// # Examples: Not found an element return None.
135 /// ```
136 /// use json_value_search::Search;
137 /// use serde_json::Value;
138 ///
139 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
140 ///
141 /// let result = value.clone().search_by_fields(&vec!["not_found"]);
142 /// match result {
143 /// Ok(None) => (),
144 /// Ok(Some(_)) => panic!("Should return None"),
145 /// Err(e) => panic!(format!("Should not be in error, {}", e))
146 /// };
147 /// ```
148 /// # Examples: Write a bad regex return an error.
149 /// ```
150 /// use json_value_search::Search;
151 /// use serde_json::Value;
152 ///
153 /// let value: Value = serde_json::from_str(r#"{"field_A":[{"field.B":"value_B"},{"field_C":"value_C"}]}"#).unwrap();
154 ///
155 /// let result = value.clone().search_by_fields(&vec!["["]);
156 /// match result {
157 /// Ok(_) => panic!("Should return an error"),
158 /// Err(e) => ()
159 /// };
160 /// ```
161 fn search_by_fields(&self, fields: &[&str]) -> io::Result<Option<Value>> {
162 if fields.is_empty() {
163 return Ok(Some(self.clone()));
164 }
165
166 let field = fields[0];
167 let remaining_fields = &fields[1..];
168
169 let index = field.parse::<usize>().ok();
170 if let Some(value) = search_by_number(self, index, remaining_fields)? {
171 return Ok(Some(value));
172 }
173
174 if let Some(value) = search_by_str(self, field, remaining_fields)? {
175 return Ok(Some(value));
176 }
177
178 Ok(None)
179 }
180}
181
182#[inline]
183fn search_by_number(
184 value: &Value,
185 index: Option<usize>,
186 fields: &[&str],
187) -> io::Result<Option<Value>> {
188 match (value, index) {
189 (Value::Array(v), Some(index)) => match v.get(index) {
190 Some(value) => value.search_by_fields(fields),
191 None => Ok(None),
192 },
193 (_, _) => Ok(None),
194 }
195}
196
197#[inline]
198fn search_by_str(value: &Value, current_field: &str, fields: &[&str]) -> io::Result<Option<Value>> {
199 match (value, current_field) {
200 (Value::Array(_), "*") => value.search_by_fields(fields),
201
202 (Value::Array(vec), _) => {
203 let mut searched_array: Vec<Value> = Vec::with_capacity(vec.len());
204 for value_tmp in vec {
205 if let Some(searched_value) = search_by_str(value_tmp, current_field, fields)? {
206 match searched_value {
207 Value::Array(mut inner_values) => searched_array.append(&mut inner_values),
208 _ => searched_array.push(searched_value),
209 }
210 }
211 }
212 if searched_array.is_empty() {
213 Ok(None)
214 } else {
215 Ok(Some(Value::Array(searched_array)))
216 }
217 }
218
219 (Value::Object(m), _) => {
220 let re = get_or_create_regex(current_field)
221 .map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, e))?;
222 for (key, value_tmp) in m {
223 if re.is_match(key.as_str()) {
224 return value_tmp.search_by_fields(fields);
225 }
226 }
227 Ok(None)
228 }
229
230 _ => Ok(None),
231 }
232}