Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions src/object.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use std::{ ptr, mem, str, slice, fmt };
use std::ops::{ Index, IndexMut, Deref };

use value::JsonValue;

const KEY_BUF_LEN: usize = 32;
static NULL: JsonValue = JsonValue::Null;

struct Node {
// Internal buffer to store keys that fit within `KEY_BUF_LEN`,
Expand Down Expand Up @@ -575,3 +577,90 @@ impl<'a> DoubleEndedIterator for IterMut<'a> {
self.inner.next_back().map(|node| (node.key_str(), &mut node.value))
}
}

/// Implements indexing by `&str` to easily access object members:
///
/// ## Example
///
/// ```
/// # #[macro_use]
/// # extern crate json;
/// # use json::JsonValue;
/// #
/// # fn main() {
/// let value = object!{
/// "foo" => "bar"
/// };
///
/// if let JsonValue::Object(object) = value {
/// assert!(object["foo"] == "bar");
/// }
/// # }
/// ```
// TODO: doc
impl<'a> Index<&'a str> for Object {
type Output = JsonValue;

fn index(&self, index: &str) -> &JsonValue {
match self.get(index) {
Some(value) => value,
_ => &NULL
}
}
}

impl Index<String> for Object {
type Output = JsonValue;

fn index(&self, index: String) -> &JsonValue {
self.index(index.deref())
}
}

impl<'a> Index<&'a String> for Object {
type Output = JsonValue;

fn index(&self, index: &String) -> &JsonValue {
self.index(index.deref())
}
}

/// Implements mutable indexing by `&str` to easily modify object members:
///
/// ## Example
///
/// ```
/// # #[macro_use]
/// # extern crate json;
/// # use json::JsonValue;
/// #
/// # fn main() {
/// let value = object!{};
///
/// if let JsonValue::Object(mut object) = value {
/// object["foo"] = 42.into();
///
/// assert!(object["foo"] == 42);
/// }
/// # }
/// ```
impl<'a> IndexMut<&'a str> for Object {
fn index_mut(&mut self, index: &str) -> &mut JsonValue {
if self.get(index).is_none() {
self.insert(index, JsonValue::Null);
}
self.get_mut(index).unwrap()
}
}

impl IndexMut<String> for Object {
fn index_mut(&mut self, index: String) -> &mut JsonValue {
self.index_mut(index.deref())
}
}

impl<'a> IndexMut<&'a String> for Object {
fn index_mut(&mut self, index: &String) -> &mut JsonValue {
self.index_mut(index.deref())
}
}
10 changes: 2 additions & 8 deletions src/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,10 +586,7 @@ impl<'a> Index<&'a str> for JsonValue {

fn index(&self, index: &str) -> &JsonValue {
match *self {
JsonValue::Object(ref object) => match object.get(index) {
Some(value) => value,
_ => &NULL
},
JsonValue::Object(ref object) => &object[index],
_ => &NULL
}
}
Expand Down Expand Up @@ -631,10 +628,7 @@ impl<'a> IndexMut<&'a str> for JsonValue {
fn index_mut(&mut self, index: &str) -> &mut JsonValue {
match *self {
JsonValue::Object(ref mut object) => {
if object.get(index).is_none() {
object.insert(index, JsonValue::Null);
}
object.get_mut(index).unwrap()
&mut object[index]
},
_ => {
*self = JsonValue::new_object();
Expand Down
77 changes: 77 additions & 0 deletions tests/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,83 @@ fn index_mut_by_string_ref() {
assert_eq!(data["foo"], "bar");
}

#[test]
fn object_index_by_str() {
let val = object!{
"foo" => "bar"
};
if let JsonValue::Object(data) = val {
assert_eq!(data["foo"], "bar");
}
}

#[test]
fn object_index_by_string() {
let val = object!{
"foo" => "bar"
};

if let JsonValue::Object(data) = val {
assert_eq!(data["foo".to_string()], "bar");
}
}

#[test]
fn object_index_by_string_ref() {
let val = object!{
"foo" => "bar"
};

let key = "foo".to_string();
let ref key_ref = key;

if let JsonValue::Object(data) = val {
assert_eq!(data[key_ref], "bar");
}
}

#[test]
fn object_index_mut_by_str() {
let val = object!{
"foo" => Null
};

if let JsonValue::Object(mut data) = val {
data["foo"] = "bar".into();

assert_eq!(data["foo"], "bar");
}
}

#[test]
fn object_index_mut_by_string() {
let val = object!{
"foo" => Null
};

if let JsonValue::Object(mut data) = val {
data["foo".to_string()] = "bar".into();

assert_eq!(data["foo"], "bar");
}
}

#[test]
fn object_index_mut_by_string_ref() {
let val = object!{
"foo" => Null
};

let key = "foo".to_string();
let ref key_ref = key;

if let JsonValue::Object(mut data) = val {
data[key_ref] = "bar".into();

assert_eq!(data["foo"], "bar");
}
}

#[test]
fn fmt_string() {
let data: JsonValue = "foobar".into();
Expand Down