From c61e740572f4e88abee8cbfdde9b203b9490c40d Mon Sep 17 00:00:00 2001 From: Sergio Benitez Date: Wed, 28 Dec 2016 21:01:16 -0600 Subject: [PATCH] Allow any Serialize type in RHS of map macro. --- contrib/src/json/mod.rs | 34 +++++++++++++++++++++++----------- contrib/src/lib.rs | 5 ++++- examples/json/src/main.rs | 6 ++++-- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/contrib/src/json/mod.rs b/contrib/src/json/mod.rs index 1b9ff79e..9cc42380 100644 --- a/contrib/src/json/mod.rs +++ b/contrib/src/json/mod.rs @@ -14,6 +14,11 @@ use self::serde::{Serialize, Deserialize}; pub use self::serde_json::error::Error as SerdeError; +pub use self::serde_json::value::Value; + +#[doc(hidden)] +pub use self::serde_json::to_value; + /// The JSON type, which implements `FromData` and `Responder`. This type allows /// you to trivially consume and respond with JSON in your Rocket application. /// @@ -117,31 +122,38 @@ impl DerefMut for JSON { } } -/// A nice little macro to create simple HashMaps. Really convenient for +/// A nice little macro to create JSON serializable HashMaps, convenient for /// returning ad-hoc JSON messages. /// +/// Keys can be any type that implements `Serialize`. All keys must have the +/// same type, which is usually an `&'static str`. Values can be any type that +/// implements `Serialize` as well, but each value is allowed to be a different +/// type. +/// /// # Examples /// /// ``` /// # #[macro_use] extern crate rocket_contrib; -/// use std::collections::HashMap; /// # fn main() { -/// let map: HashMap<&str, usize> = map! { -/// "status" => 0, -/// "count" => 100 +/// let map = map! { +/// "message" => "Done!", +/// "success" => true, +/// "count" => 3, /// }; /// -/// assert_eq!(map.len(), 2); -/// assert_eq!(map.get("status"), Some(&0)); -/// assert_eq!(map.get("count"), Some(&100)); +/// assert_eq!(map.len(), 3); +/// assert_eq!(map.get("message").and_then(|v| v.as_str()), Some("Done!")); +/// assert_eq!(map.get("success").and_then(|v| v.as_bool()), Some(true)); +/// assert_eq!(map.get("count").and_then(|v| v.as_u64()), Some(3)); /// # } /// ``` #[macro_export] macro_rules! map { ($($key:expr => $value:expr),+) => ({ - use std::collections::HashMap; - let mut map = HashMap::new(); - $(map.insert($key, $value);)+ + use ::std::collections::HashMap; + use $crate::json::{Value, to_value}; + let mut map: HashMap<_, Value> = HashMap::new(); + $(map.insert($key, to_value($value));)+ map }); diff --git a/contrib/src/lib.rs b/contrib/src/lib.rs index 34b518b9..3a665595 100644 --- a/contrib/src/lib.rs +++ b/contrib/src/lib.rs @@ -42,7 +42,8 @@ extern crate lazy_static; #[cfg_attr(feature = "json", macro_use)] #[cfg(feature = "json")] -mod json; +#[doc(hidden)] +pub mod json; #[cfg(feature = "templates")] mod templates; @@ -52,6 +53,8 @@ mod uuid; #[cfg(feature = "json")] pub use json::JSON; +#[cfg(feature = "json")] +pub use json::Value; #[cfg(feature = "json")] pub use json::SerdeError; diff --git a/examples/json/src/main.rs b/examples/json/src/main.rs index 5e66d911..52351097 100644 --- a/examples/json/src/main.rs +++ b/examples/json/src/main.rs @@ -9,13 +9,15 @@ extern crate serde_json; #[cfg(test)] mod tests; -use rocket_contrib::JSON; +use rocket_contrib::{JSON, Value}; use std::collections::HashMap; use std::sync::Mutex; // The type to represent the ID of a message. type ID = usize; -type SimpleMap = HashMap<&'static str, &'static str>; + +// The type of a `map!` invocation. +type SimpleMap = HashMap<&'static str, Value>; // We're going to store all of the messages here. No need for a DB. lazy_static! {