Skip to content

Commit 9e0cfa2

Browse files
zslaytonZack Slayton
authored andcommitted
Added convenience methods and accompanying tests to the Json class.
Fixed some styling issues with trailing whitespace. - Removed redundant functions. - Renamed `get` to `find` - Renamed `get_path` to `find_path` - Renamed `find` to `search` - Changed as_object and as_list to return Object and List rather than the underlying implementation types of TreeMap<~str,Json> and ~[Json] - Refactored find_path to use a fold() instead of recursion Formatting fixes. Fixed spacing, deleted comment. Added convenience methods and accompanying tests to the Json class. Updated tests to expect less pointer indirection.
1 parent a0f20f0 commit 9e0cfa2

File tree

1 file changed

+247
-0
lines changed

1 file changed

+247
-0
lines changed

src/libserialize/json.rs

Lines changed: 247 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,148 @@ impl Json {
709709
self.to_pretty_writer(&mut s as &mut io::Writer).unwrap();
710710
str::from_utf8_owned(s.unwrap()).unwrap()
711711
}
712+
713+
/// If the Json value is an Object, returns the value associated with the provided key.
714+
/// Otherwise, returns None.
715+
pub fn find<'a>(&'a self, key: &~str) -> Option<&'a Json>{
716+
match self {
717+
&Object(ref map) => map.find(key),
718+
_ => None
719+
}
720+
}
721+
722+
/// Attempts to get a nested Json Object for each key in `keys`.
723+
/// If any key is found not to exist, get_path will return None.
724+
/// Otherwise, it will return the Json value associated with the final key.
725+
pub fn find_path<'a>(&'a self, keys: &[&~str]) -> Option<&'a Json>{
726+
keys.iter().fold(Some(self), |target, key| target.map_or(None, |t| t.find(*key)))
727+
}
728+
729+
/// If the Json value is an Object, performs a depth-first search until
730+
/// a value associated with the provided key is found. If no value is found
731+
/// or the Json value is not an Object, returns None.
732+
pub fn search<'a>(&'a self, key: &~str) -> Option<&'a Json> {
733+
match self {
734+
&Object(ref map) => {
735+
match map.find(key) {
736+
Some(json_value) => Some(json_value),
737+
None => {
738+
let mut value : Option<&'a Json> = None;
739+
for (_, v) in map.iter() {
740+
value = v.search(key);
741+
if value.is_some() {
742+
break;
743+
}
744+
}
745+
value
746+
}
747+
}
748+
},
749+
_ => None
750+
}
751+
}
752+
753+
/// Returns true if the Json value is an Object. Returns false otherwise.
754+
pub fn is_object<'a>(&'a self) -> bool {
755+
match self {
756+
&Object(_) => true,
757+
_ => false
758+
}
759+
}
760+
761+
/// If the Json value is an Object, returns the associated TreeMap.
762+
/// Returns None otherwise.
763+
pub fn as_object<'a>(&'a self) -> Option<&'a Object> {
764+
match self {
765+
&Object(ref map) => Some(&**map),
766+
_ => None
767+
}
768+
}
769+
770+
/// Returns true if the Json value is a List. Returns false otherwise.
771+
pub fn is_list<'a>(&'a self) -> bool {
772+
match self {
773+
&List(_) => true,
774+
_ => false
775+
}
776+
}
777+
778+
/// If the Json value is a List, returns the associated vector.
779+
/// Returns None otherwise.
780+
pub fn as_list<'a>(&'a self) -> Option<&'a List> {
781+
match self {
782+
&List(ref list) => Some(&*list),
783+
_ => None
784+
}
785+
}
786+
787+
/// Returns true if the Json value is a String. Returns false otherwise.
788+
pub fn is_str<'a>(&'a self) -> bool {
789+
match self {
790+
&String(_) => true,
791+
_ => false
792+
}
793+
}
794+
795+
/// If the Json value is a String, returns the associated str.
796+
/// Returns None otherwise.
797+
pub fn as_str<'a>(&'a self) -> Option<&'a str> {
798+
match *self {
799+
String(ref s) => Some(s.as_slice()),
800+
_ => None
801+
}
802+
}
803+
804+
/// Returns true if the Json value is a Number. Returns false otherwise.
805+
pub fn is_number(&self) -> bool {
806+
match self {
807+
&Number(_) => true,
808+
_ => false
809+
}
810+
}
811+
812+
/// If the Json value is a Number, returns the associated f64.
813+
/// Returns None otherwise.
814+
pub fn as_number(&self) -> Option<f64> {
815+
match self {
816+
&Number(n) => Some(n),
817+
_ => None
818+
}
819+
}
820+
821+
/// Returns true if the Json value is a Boolean. Returns false otherwise.
822+
pub fn is_boolean(&self) -> bool {
823+
match self {
824+
&Boolean(_) => true,
825+
_ => false
826+
}
827+
}
828+
829+
/// If the Json value is a Boolean, returns the associated bool.
830+
/// Returns None otherwise.
831+
pub fn as_boolean(&self) -> Option<bool> {
832+
match self {
833+
&Boolean(b) => Some(b),
834+
_ => None
835+
}
836+
}
837+
838+
/// Returns true if the Json value is a Null. Returns false otherwise.
839+
pub fn is_null(&self) -> bool {
840+
match self {
841+
&Null => true,
842+
_ => false
843+
}
844+
}
845+
846+
/// If the Json value is a Null, returns ().
847+
/// Returns None otherwise.
848+
pub fn as_null(&self) -> Option<()> {
849+
match self {
850+
&Null => Some(()),
851+
_ => None
852+
}
853+
}
712854
}
713855

714856
pub struct Parser<T> {
@@ -2283,4 +2425,109 @@ mod tests {
22832425
check_err::<DecodeEnum>("{\"variant\": \"C\", \"fields\": []}",
22842426
"unknown variant name");
22852427
}
2428+
2429+
#[test]
2430+
fn test_find(){
2431+
let json_value = from_str("{\"dog\" : \"cat\"}").unwrap();
2432+
let found_str = json_value.find(&~"dog");
2433+
assert!(found_str.is_some() && found_str.unwrap().as_str().unwrap() == &"cat");
2434+
}
2435+
2436+
#[test]
2437+
fn test_find_path(){
2438+
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
2439+
let found_str = json_value.find_path(&[&~"dog", &~"cat", &~"mouse"]);
2440+
assert!(found_str.is_some() && found_str.unwrap().as_str().unwrap() == &"cheese");
2441+
}
2442+
2443+
#[test]
2444+
fn test_search(){
2445+
let json_value = from_str("{\"dog\":{\"cat\": {\"mouse\" : \"cheese\"}}}").unwrap();
2446+
let found_str = json_value.search(&~"mouse").and_then(|j| j.as_str());
2447+
assert!(found_str.is_some());
2448+
assert!(found_str.unwrap() == &"cheese");
2449+
}
2450+
2451+
#[test]
2452+
fn test_is_object(){
2453+
let json_value = from_str("{}").unwrap();
2454+
assert!(json_value.is_object());
2455+
}
2456+
2457+
#[test]
2458+
fn test_as_object(){
2459+
let json_value = from_str("{}").unwrap();
2460+
let json_object = json_value.as_object();
2461+
assert!(json_object.is_some());
2462+
}
2463+
2464+
#[test]
2465+
fn test_is_list(){
2466+
let json_value = from_str("[1, 2, 3]").unwrap();
2467+
assert!(json_value.is_list());
2468+
}
2469+
2470+
#[test]
2471+
fn test_as_list(){
2472+
let json_value = from_str("[1, 2, 3]").unwrap();
2473+
let json_list = json_value.as_list();
2474+
let expected_length = 3;
2475+
assert!(json_list.is_some() && json_list.unwrap().len() == expected_length);
2476+
}
2477+
2478+
#[test]
2479+
fn test_is_str(){
2480+
let json_value = from_str("\"dog\"").unwrap();
2481+
assert!(json_value.is_str());
2482+
}
2483+
2484+
#[test]
2485+
fn test_as_str(){
2486+
let json_value = from_str("\"dog\"").unwrap();
2487+
let json_str = json_value.as_str();
2488+
let expected_str = &"dog";
2489+
assert_eq!(json_str, Some(expected_str));
2490+
}
2491+
2492+
#[test]
2493+
fn test_is_number(){
2494+
let json_value = from_str("12").unwrap();
2495+
assert!(json_value.is_number());
2496+
}
2497+
2498+
#[test]
2499+
fn test_as_number(){
2500+
let json_value = from_str("12").unwrap();
2501+
let json_num = json_value.as_number();
2502+
let expected_num = 12f64;
2503+
assert!(json_num.is_some() && json_num.unwrap() == expected_num);
2504+
}
2505+
2506+
#[test]
2507+
fn test_is_boolean(){
2508+
let json_value = from_str("false").unwrap();
2509+
assert!(json_value.is_boolean());
2510+
}
2511+
2512+
#[test]
2513+
fn test_as_boolean(){
2514+
let json_value = from_str("false").unwrap();
2515+
let json_bool = json_value.as_boolean();
2516+
let expected_bool = false;
2517+
assert!(json_bool.is_some() && json_bool.unwrap() == expected_bool);
2518+
}
2519+
2520+
#[test]
2521+
fn test_is_null(){
2522+
let json_value = from_str("null").unwrap();
2523+
assert!(json_value.is_null());
2524+
}
2525+
2526+
#[test]
2527+
fn test_as_null(){
2528+
let json_value = from_str("null").unwrap();
2529+
let json_null = json_value.as_null();
2530+
let expected_null = ();
2531+
assert!(json_null.is_some() && json_null.unwrap() == expected_null);
2532+
}
22862533
}

0 commit comments

Comments
 (0)