diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 84b5cdd3cc82b..31d306b01c31f 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -203,6 +203,7 @@ use std::num::{FPNaN, FPInfinite}; use std::str::ScalarValue; use std::string; use std::vec::Vec; +use std::ops; use Encodable; @@ -884,9 +885,9 @@ impl Json { /// If the Json value is an Object, returns the value associated with the provided key. /// Otherwise, returns None. - pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Json>{ + pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{ match self { - &Object(ref map) => map.find(key), + &Object(ref map) => map.find_with(|s| key.cmp(&s.as_slice())), _ => None } } @@ -894,7 +895,7 @@ impl Json { /// Attempts to get a nested Json Object for each key in `keys`. /// If any key is found not to exist, find_path will return None. /// Otherwise, it will return the Json value associated with the final key. - pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Json>{ + pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Json>{ let mut target = self; for key in keys.iter() { match target.find(*key) { @@ -908,20 +909,19 @@ impl Json { /// If the Json value is an Object, performs a depth-first search until /// a value associated with the provided key is found. If no value is found /// or the Json value is not an Object, returns None. - pub fn search<'a>(&'a self, key: &string::String) -> Option<&'a Json> { + pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> { match self { &Object(ref map) => { - match map.find(key) { + match map.find_with(|s| key.cmp(&s.as_slice())) { Some(json_value) => Some(json_value), None => { - let mut value : Option<&'a Json> = None; for (_, v) in map.iter() { - value = v.search(key); - if value.is_some() { - break; + match v.search(key) { + x if x.is_some() => return x, + _ => () } } - value + None } } }, @@ -1063,6 +1063,21 @@ impl Json { } } +impl<'a> ops::Index<&'a str, Json> for Json { + fn index<'a>(&'a self, idx: & &str) -> &'a Json { + self.find(*idx).unwrap() + } +} + +impl ops::Index for Json { + fn index<'a>(&'a self, idx: &uint) -> &'a Json { + match self { + &List(ref v) => v.index(idx), + _ => panic!("can only index Json with uint if it is a list") + } + } +} + /// The output of the streaming parser. #[deriving(PartialEq, Clone, Show)] pub enum JsonEvent { @@ -3055,26 +3070,33 @@ mod tests { #[test] fn test_find(){ let json_value = from_str("{\"dog\" : \"cat\"}").unwrap(); - let found_str = json_value.find(&"dog".to_string()); - assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat"); + let found_str = json_value.find("dog"); + assert!(found_str.unwrap().as_string().unwrap() == "cat"); } #[test] fn test_find_path(){ let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.find_path(&[&"dog".to_string(), - &"cat".to_string(), &"mouse".to_string()]); - assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese"); + let found_str = json_value.find_path(&["dog", "cat", "mouse"]); + assert!(found_str.unwrap().as_string().unwrap() == "cheese"); } #[test] fn test_search(){ let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); - let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string()); - assert!(found_str.is_some()); + let found_str = json_value.search("mouse").and_then(|j| j.as_string()); assert!(found_str.unwrap() == "cheese"); } + #[test] + fn test_index(){ + let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap(); + let ref list = json_value["animals"]; + assert_eq!(list[0].as_string().unwrap(), "dog"); + assert_eq!(list[1].as_string().unwrap(), "cat"); + assert_eq!(list[2].as_string().unwrap(), "mouse"); + } + #[test] fn test_is_object(){ let json_value = from_str("{}").unwrap();