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}