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