mirror of https://github.com/rwf2/Rocket.git
Update to serde 0.9, handlebars 0.25. Move from `map!` to `json!` macro.
Resolves #154.
This commit is contained in:
parent
52d627cf44
commit
5fabb43a1b
|
@ -28,11 +28,11 @@ log = "^0.3"
|
||||||
uuid = { version = "^0.3", optional = true }
|
uuid = { version = "^0.3", optional = true }
|
||||||
|
|
||||||
# JSON and templating dependencies.
|
# JSON and templating dependencies.
|
||||||
serde = { version = "^0.8", optional = true }
|
serde = { version = "^0.9", optional = true }
|
||||||
serde_json = { version = "^0.8", optional = true }
|
serde_json = { version = "^0.9.3", optional = true }
|
||||||
|
|
||||||
# Templating dependencies only.
|
# Templating dependencies only.
|
||||||
handlebars = { version = "^0.24", optional = true, features = ["serde_type"] }
|
handlebars = { version = "^0.25", optional = true, features = ["serde_type"] }
|
||||||
glob = { version = "^0.2", optional = true }
|
glob = { version = "^0.2", optional = true }
|
||||||
lazy_static = { version = "^0.2", optional = true }
|
lazy_static = { version = "^0.2", optional = true }
|
||||||
# tera = { version = "^0.6", optional = true }
|
# tera = { version = "^0.6", optional = true }
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
extern crate serde;
|
|
||||||
extern crate serde_json;
|
|
||||||
|
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
|
@ -10,17 +7,15 @@ use rocket::data::{self, Data, FromData};
|
||||||
use rocket::response::{self, Responder, content};
|
use rocket::response::{self, Responder, content};
|
||||||
use rocket::http::Status;
|
use rocket::http::Status;
|
||||||
|
|
||||||
use self::serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
pub use self::serde_json::error::Error as SerdeError;
|
use serde_json;
|
||||||
|
|
||||||
pub use self::serde_json::value::Value;
|
pub use serde_json::Value;
|
||||||
|
pub use serde_json::error::Error as SerdeError;
|
||||||
|
|
||||||
#[doc(hidden)]
|
/// The JSON type: implements `FromData` and `Responder`, allowing you to easily
|
||||||
pub use self::serde_json::to_value;
|
/// consume and respond with JSON.
|
||||||
|
|
||||||
/// The JSON type, which implements `FromData` and `Responder`. This type allows
|
|
||||||
/// you to trivially consume and respond with JSON in your Rocket application.
|
|
||||||
///
|
///
|
||||||
/// If you're receiving JSON data, simple add a `data` parameter to your route
|
/// If you're receiving JSON data, simple add a `data` parameter to your route
|
||||||
/// arguments and ensure the type o the parameter is a `JSON<T>`, where `T` is
|
/// arguments and ensure the type o the parameter is a `JSON<T>`, where `T` is
|
||||||
|
@ -122,42 +117,104 @@ impl<T> DerefMut for JSON<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A nice little macro to create JSON serializable HashMaps, convenient for
|
/// A macro to create ad-hoc JSON serializable values using JSON syntax.
|
||||||
/// returning ad-hoc JSON messages.
|
|
||||||
///
|
///
|
||||||
/// Keys can be any type that implements `Serialize`. All keys must have the
|
/// # Usage
|
||||||
/// 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
|
/// To import the macro, add the `#[macro_use]` attribute to the `extern crate
|
||||||
/// type.
|
/// rocket_contrib` invocation:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// The return type of a macro invocation is
|
||||||
|
/// [Value](/rocket_contrib/enum.Value.html). A value created with this macro
|
||||||
|
/// can be returned from a handler as follows:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// use rocket_contrib::{JSON, Value};
|
||||||
|
///
|
||||||
|
/// #[get("/json")]
|
||||||
|
/// fn get_json() -> JSON<Value> {
|
||||||
|
/// JSON(json!({
|
||||||
|
/// "key": "value",
|
||||||
|
/// "array": [1, 2, 3, 4]
|
||||||
|
/// }))
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// Create a simple JSON object with two keys: `"username"` and `"id"`:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #![allow(unused_variables)]
|
||||||
/// # #[macro_use] extern crate rocket_contrib;
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
/// # fn main() {
|
/// # fn main() {
|
||||||
/// let map = map! {
|
/// let value = json!({
|
||||||
/// "message" => "Done!",
|
/// "username": "mjordan",
|
||||||
/// "success" => true,
|
/// "id": 23
|
||||||
/// "count" => 3,
|
/// });
|
||||||
/// };
|
/// # }
|
||||||
|
/// ```
|
||||||
///
|
///
|
||||||
/// assert_eq!(map.len(), 3);
|
/// Create a more complex object with a nested object and array:
|
||||||
/// 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));
|
/// ```rust
|
||||||
/// assert_eq!(map.get("count").and_then(|v| v.as_u64()), Some(3));
|
/// # #![allow(unused_variables)]
|
||||||
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// # fn main() {
|
||||||
|
/// let value = json!({
|
||||||
|
/// "code": 200,
|
||||||
|
/// "success": true,
|
||||||
|
/// "payload": {
|
||||||
|
/// "features": ["serde", "json"],
|
||||||
|
/// "ids": [12, 121],
|
||||||
|
/// },
|
||||||
|
/// });
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Variables or expressions can be interpolated into the JSON literal. Any type
|
||||||
|
/// interpolated into an array element or object value must implement Serde's
|
||||||
|
/// `Serialize` trait, while any type interpolated into a object key must
|
||||||
|
/// implement `Into<String>`.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #![allow(unused_variables)]
|
||||||
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// # fn main() {
|
||||||
|
/// let code = 200;
|
||||||
|
/// let features = vec!["serde", "json"];
|
||||||
|
///
|
||||||
|
/// let value = json!({
|
||||||
|
/// "code": code,
|
||||||
|
/// "success": code == 200,
|
||||||
|
/// "payload": {
|
||||||
|
/// features[0]: features[1]
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Trailing commas are allowed inside both arrays and objects.
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # #![allow(unused_variables)]
|
||||||
|
/// # #[macro_use] extern crate rocket_contrib;
|
||||||
|
/// # fn main() {
|
||||||
|
/// let value = json!([
|
||||||
|
/// "notice",
|
||||||
|
/// "the",
|
||||||
|
/// "trailing",
|
||||||
|
/// "comma -->",
|
||||||
|
/// ]);
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! map {
|
macro_rules! json {
|
||||||
($($key:expr => $value:expr),+) => ({
|
($($json:tt)+) => {
|
||||||
use ::std::collections::HashMap;
|
json_internal!($($json)+)
|
||||||
use $crate::json::{Value, to_value};
|
|
||||||
let mut map: HashMap<_, Value> = HashMap::new();
|
|
||||||
$(map.insert($key, to_value($value));)+
|
|
||||||
map
|
|
||||||
});
|
|
||||||
|
|
||||||
($($key:expr => $value:expr),+,) => {
|
|
||||||
map!($($key => $value),+)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(drop_types_in_const)]
|
#![feature(drop_types_in_const, macro_reexport)]
|
||||||
|
|
||||||
//! This crate contains officially sanctioned contributor libraries that provide
|
//! This crate contains officially sanctioned contributor libraries that provide
|
||||||
//! functionality commonly used by Rocket applications.
|
//! functionality commonly used by Rocket applications.
|
||||||
|
@ -40,27 +40,29 @@
|
||||||
#[cfg(feature = "lazy_static_macro")]
|
#[cfg(feature = "lazy_static_macro")]
|
||||||
extern crate lazy_static;
|
extern crate lazy_static;
|
||||||
|
|
||||||
#[cfg_attr(feature = "json", macro_use)]
|
#[cfg(feature = "serde")]
|
||||||
|
extern crate serde;
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
|
#[cfg_attr(feature = "json", macro_reexport(json_internal))]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
|
#[cfg(feature = "json")]
|
||||||
|
#[cfg_attr(feature = "json", macro_use)]
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod json;
|
pub mod json;
|
||||||
|
|
||||||
|
#[cfg(feature = "json")]
|
||||||
|
pub use json::{JSON, SerdeError, Value};
|
||||||
|
|
||||||
#[cfg(feature = "templates")]
|
#[cfg(feature = "templates")]
|
||||||
mod templates;
|
mod templates;
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
|
||||||
mod uuid;
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
pub use json::JSON;
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
pub use json::Value;
|
|
||||||
|
|
||||||
#[cfg(feature = "json")]
|
|
||||||
pub use json::SerdeError;
|
|
||||||
|
|
||||||
#[cfg(feature = "templates")]
|
#[cfg(feature = "templates")]
|
||||||
pub use templates::Template;
|
pub use templates::Template;
|
||||||
|
|
||||||
|
#[cfg(feature = "uuid")]
|
||||||
|
mod uuid;
|
||||||
|
|
||||||
#[cfg(feature = "uuid")]
|
#[cfg(feature = "uuid")]
|
||||||
pub use uuid::{UUID, UuidParseError};
|
pub use uuid::{UUID, UuidParseError};
|
||||||
|
|
|
@ -142,6 +142,7 @@ impl Template {
|
||||||
///
|
///
|
||||||
/// # context.insert("test", "test");
|
/// # context.insert("test", "test");
|
||||||
/// let template = Template::render("index", &context);
|
/// let template = Template::render("index", &context);
|
||||||
|
/// # assert_eq!(template.to_string(), "");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn render<S, T>(name: S, context: &T) -> Template
|
pub fn render<S, T>(name: S, context: &T) -> Template
|
||||||
where S: AsRef<str>, T: Serialize
|
where S: AsRef<str>, T: Serialize
|
||||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../lib" }
|
rocket = { path = "../../lib" }
|
||||||
rocket_codegen = { path = "../../codegen" }
|
rocket_codegen = { path = "../../codegen" }
|
||||||
serde = "0.8"
|
serde = "0.9"
|
||||||
serde_json = "0.8"
|
serde_json = "0.9"
|
||||||
serde_derive = "0.8"
|
serde_derive = "0.9"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rocket = { path = "../../lib", features = ["testing"] }
|
rocket = { path = "../../lib", features = ["testing"] }
|
||||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../lib" }
|
rocket = { path = "../../lib" }
|
||||||
rocket_codegen = { path = "../../codegen" }
|
rocket_codegen = { path = "../../codegen" }
|
||||||
serde = "0.8"
|
serde = "0.9"
|
||||||
serde_derive = "0.8"
|
serde_derive = "0.9"
|
||||||
serde_json = "0.8"
|
serde_json = "0.9"
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
path = "../../contrib"
|
path = "../../contrib"
|
||||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../lib" }
|
rocket = { path = "../../lib" }
|
||||||
rocket_codegen = { path = "../../codegen" }
|
rocket_codegen = { path = "../../codegen" }
|
||||||
serde = "0.8"
|
serde = "0.9"
|
||||||
serde_json = "0.8"
|
serde_json = "0.9"
|
||||||
serde_derive = "0.8"
|
serde_derive = "0.9"
|
||||||
lazy_static = "*"
|
lazy_static = "*"
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
|
|
|
@ -16,9 +16,6 @@ use std::sync::Mutex;
|
||||||
// The type to represent the ID of a message.
|
// The type to represent the ID of a message.
|
||||||
type ID = usize;
|
type ID = usize;
|
||||||
|
|
||||||
// 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.
|
// We're going to store all of the messages here. No need for a DB.
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref MAP: Mutex<HashMap<ID, String>> = Mutex::new(HashMap::new());
|
static ref MAP: Mutex<HashMap<ID, String>> = Mutex::new(HashMap::new());
|
||||||
|
@ -32,25 +29,25 @@ struct Message {
|
||||||
|
|
||||||
// TODO: This example can be improved by using `route` with muliple HTTP verbs.
|
// TODO: This example can be improved by using `route` with muliple HTTP verbs.
|
||||||
#[post("/<id>", format = "application/json", data = "<message>")]
|
#[post("/<id>", format = "application/json", data = "<message>")]
|
||||||
fn new(id: ID, message: JSON<Message>) -> JSON<SimpleMap> {
|
fn new(id: ID, message: JSON<Message>) -> JSON<Value> {
|
||||||
let mut hashmap = MAP.lock().expect("map lock.");
|
let mut hashmap = MAP.lock().expect("map lock.");
|
||||||
if hashmap.contains_key(&id) {
|
if hashmap.contains_key(&id) {
|
||||||
JSON(map!{
|
JSON(json!({
|
||||||
"status" => "error",
|
"status": "error",
|
||||||
"reason" => "ID exists. Try put."
|
"reason": "ID exists. Try put."
|
||||||
})
|
}))
|
||||||
} else {
|
} else {
|
||||||
hashmap.insert(id, message.0.contents);
|
hashmap.insert(id, message.0.contents);
|
||||||
JSON(map!{ "status" => "ok" })
|
JSON(json!({ "status": "ok" }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/<id>", format = "application/json", data = "<message>")]
|
#[put("/<id>", format = "application/json", data = "<message>")]
|
||||||
fn update(id: ID, message: JSON<Message>) -> Option<JSON<SimpleMap>> {
|
fn update(id: ID, message: JSON<Message>) -> Option<JSON<Value>> {
|
||||||
let mut hashmap = MAP.lock().unwrap();
|
let mut hashmap = MAP.lock().unwrap();
|
||||||
if hashmap.contains_key(&id) {
|
if hashmap.contains_key(&id) {
|
||||||
hashmap.insert(id, message.0.contents);
|
hashmap.insert(id, message.0.contents);
|
||||||
Some(JSON(map!{ "status" => "ok" }))
|
Some(JSON(json!({ "status": "ok" })))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -68,11 +65,11 @@ fn get(id: ID) -> Option<JSON<Message>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[error(404)]
|
#[error(404)]
|
||||||
fn not_found() -> JSON<SimpleMap> {
|
fn not_found() -> JSON<Value> {
|
||||||
JSON(map! {
|
JSON(json!({
|
||||||
"status" => "error",
|
"status": "error",
|
||||||
"reason" => "Resource was not found."
|
"reason": "Resource was not found."
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rocket = { path = "../../lib" }
|
rocket = { path = "../../lib" }
|
||||||
rocket_codegen = { path = "../../codegen" }
|
rocket_codegen = { path = "../../codegen" }
|
||||||
serde = "0.8"
|
serde = "0.9"
|
||||||
serde_json = "0.8"
|
serde_json = "0.9"
|
||||||
serde_derive = "0.8"
|
serde_derive = "0.9"
|
||||||
diesel = { version = "0.9", features = ["sqlite"] }
|
diesel = { version = "0.9", features = ["sqlite"] }
|
||||||
diesel_codegen = { version = "0.9", features = ["sqlite"] }
|
diesel_codegen = { version = "0.9", features = ["sqlite"] }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue