Skip to content

Commit ab9a1b7

Browse files
author
whataloadofwhat
committed
Change Json methods to &str and allow Indexing
Json's find, find_path, and search methods now use &str rather than &String. Json can now be indexed with &str (for Objects) and uint (for Lists). Tests updated to reflect this change. [breaking-change]
1 parent 0547a40 commit ab9a1b7

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

src/libserialize/json.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ use std::num::{FPNaN, FPInfinite};
203203
use std::str::ScalarValue;
204204
use std::string;
205205
use std::vec::Vec;
206+
use std::ops;
206207

207208
use Encodable;
208209

@@ -884,17 +885,17 @@ impl Json {
884885

885886
/// If the Json value is an Object, returns the value associated with the provided key.
886887
/// Otherwise, returns None.
887-
pub fn find<'a>(&'a self, key: &string::String) -> Option<&'a Json>{
888+
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
888889
match self {
889-
&Object(ref map) => map.find(key),
890+
&Object(ref map) => map.find_with(|s| key.cmp(&s.as_slice())),
890891
_ => None
891892
}
892893
}
893894

894895
/// Attempts to get a nested Json Object for each key in `keys`.
895896
/// If any key is found not to exist, find_path will return None.
896897
/// Otherwise, it will return the Json value associated with the final key.
897-
pub fn find_path<'a>(&'a self, keys: &[&string::String]) -> Option<&'a Json>{
898+
pub fn find_path<'a>(&'a self, keys: &[&str]) -> Option<&'a Json>{
898899
let mut target = self;
899900
for key in keys.iter() {
900901
match target.find(*key) {
@@ -908,20 +909,19 @@ impl Json {
908909
/// If the Json value is an Object, performs a depth-first search until
909910
/// a value associated with the provided key is found. If no value is found
910911
/// or the Json value is not an Object, returns None.
911-
pub fn search<'a>(&'a self, key: &string::String) -> Option<&'a Json> {
912+
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
912913
match self {
913914
&Object(ref map) => {
914-
match map.find(key) {
915+
match map.find_with(|s| key.cmp(&s.as_slice())) {
915916
Some(json_value) => Some(json_value),
916917
None => {
917-
let mut value : Option<&'a Json> = None;
918918
for (_, v) in map.iter() {
919-
value = v.search(key);
920-
if value.is_some() {
921-
break;
919+
match v.search(key) {
920+
x if x.is_some() => return x,
921+
_ => ()
922922
}
923923
}
924-
value
924+
None
925925
}
926926
}
927927
},
@@ -1063,6 +1063,21 @@ impl Json {
10631063
}
10641064
}
10651065

1066+
impl<'a> ops::Index<&'a str, Json> for Json {
1067+
fn index<'a>(&'a self, idx: & &str) -> &'a Json {
1068+
self.find(*idx).unwrap()
1069+
}
1070+
}
1071+
1072+
impl ops::Index<uint, Json> for Json {
1073+
fn index<'a>(&'a self, idx: &uint) -> &'a Json {
1074+
match self {
1075+
&List(ref v) => v.index(idx),
1076+
_ => panic!("can only index Json with uint if it is a list")
1077+
}
1078+
}
1079+
}
1080+
10661081
/// The output of the streaming parser.
10671082
#[deriving(PartialEq, Clone, Show)]
10681083
pub enum JsonEvent {
@@ -3055,26 +3070,33 @@ mod tests {
30553070
#[test]
30563071
fn test_find(){
30573072
let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
3058-
let found_str = json_value.find(&"dog".to_string());
3059-
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat");
3073+
let found_str = json_value.find("dog");
3074+
assert!(found_str.unwrap().as_string().unwrap() == "cat");
30603075
}
30613076

30623077
#[test]
30633078
fn test_find_path(){
30643079
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
3065-
let found_str = json_value.find_path(&[&"dog".to_string(),
3066-
&"cat".to_string(), &"mouse".to_string()]);
3067-
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese");
3080+
let found_str = json_value.find_path(&["dog", "cat", "mouse"]);
3081+
assert!(found_str.unwrap().as_string().unwrap() == "cheese");
30683082
}
30693083

30703084
#[test]
30713085
fn test_search(){
30723086
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
3073-
let found_str = json_value.search(&"mouse".to_string()).and_then(|j| j.as_string());
3074-
assert!(found_str.is_some());
3087+
let found_str = json_value.search("mouse").and_then(|j| j.as_string());
30753088
assert!(found_str.unwrap() == "cheese");
30763089
}
30773090

3091+
#[test]
3092+
fn test_index(){
3093+
let json_value = from_str("{\"animals\":[\"dog\",\"cat\",\"mouse\"]}").unwrap();
3094+
let ref list = json_value["animals"];
3095+
assert_eq!(list[0].as_string().unwrap(), "dog");
3096+
assert_eq!(list[1].as_string().unwrap(), "cat");
3097+
assert_eq!(list[2].as_string().unwrap(), "mouse");
3098+
}
3099+
30783100
#[test]
30793101
fn test_is_object(){
30803102
let json_value = from_str("{}").unwrap();

0 commit comments

Comments
 (0)