1
Fork 0

rollup merge of #18544 : whataloadofwhat/json

This commit is contained in:
Alex Crichton 2014-11-03 15:29:37 -08:00
commit dbb9c99911

View file

@ -203,6 +203,7 @@ use std::num::{FPNaN, FPInfinite};
use std::str::ScalarValue; use std::str::ScalarValue;
use std::string; use std::string;
use std::vec::Vec; use std::vec::Vec;
use std::ops;
use Encodable; use Encodable;
@ -889,9 +890,9 @@ impl Json {
/// If the Json value is an Object, returns the value associated with the provided key. /// If the Json value is an Object, returns the value associated with the provided key.
/// Otherwise, returns None. /// 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 { match self {
&Object(ref map) => map.find(key), &Object(ref map) => map.find_with(|s| key.cmp(&s.as_slice())),
_ => None _ => None
} }
} }
@ -899,7 +900,7 @@ impl Json {
/// Attempts to get a nested Json Object for each key in `keys`. /// 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. /// 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. /// 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; let mut target = self;
for key in keys.iter() { for key in keys.iter() {
match target.find(*key) { match target.find(*key) {
@ -913,20 +914,19 @@ impl Json {
/// If the Json value is an Object, performs a depth-first search until /// 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 /// a value associated with the provided key is found. If no value is found
/// or the Json value is not an Object, returns None. /// 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 { match self {
&Object(ref map) => { &Object(ref map) => {
match map.find(key) { match map.find_with(|s| key.cmp(&s.as_slice())) {
Some(json_value) => Some(json_value), Some(json_value) => Some(json_value),
None => { None => {
let mut value : Option<&'a Json> = None;
for (_, v) in map.iter() { for (_, v) in map.iter() {
value = v.search(key); match v.search(key) {
if value.is_some() { x if x.is_some() => return x,
break; _ => ()
} }
} }
value None
} }
} }
}, },
@ -1068,6 +1068,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<uint, Json> 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. /// The output of the streaming parser.
#[deriving(PartialEq, Clone, Show)] #[deriving(PartialEq, Clone, Show)]
pub enum JsonEvent { pub enum JsonEvent {
@ -3089,26 +3104,33 @@ mod tests {
#[test] #[test]
fn test_find(){ fn test_find(){
let json_value = from_str("{\"dog\" : \"cat\"}").unwrap(); let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
let found_str = json_value.find(&"dog".to_string()); let found_str = json_value.find("dog");
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cat"); assert!(found_str.unwrap().as_string().unwrap() == "cat");
} }
#[test] #[test]
fn test_find_path(){ fn test_find_path(){
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
let found_str = json_value.find_path(&[&"dog".to_string(), let found_str = json_value.find_path(&["dog", "cat", "mouse"]);
&"cat".to_string(), &"mouse".to_string()]); assert!(found_str.unwrap().as_string().unwrap() == "cheese");
assert!(found_str.is_some() && found_str.unwrap().as_string().unwrap() == "cheese");
} }
#[test] #[test]
fn test_search(){ fn test_search(){
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap(); 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()); let found_str = json_value.search("mouse").and_then(|j| j.as_string());
assert!(found_str.is_some());
assert!(found_str.unwrap() == "cheese"); 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] #[test]
fn test_is_object(){ fn test_is_object(){
let json_value = from_str("{}").unwrap(); let json_value = from_str("{}").unwrap();