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 }
|
||||
|
||||
# JSON and templating dependencies.
|
||||
serde = { version = "^0.8", optional = true }
|
||||
serde_json = { version = "^0.8", optional = true }
|
||||
serde = { version = "^0.9", optional = true }
|
||||
serde_json = { version = "^0.9.3", optional = true }
|
||||
|
||||
# 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 }
|
||||
lazy_static = { version = "^0.2", 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::io::Read;
|
||||
|
||||
|
@ -10,17 +7,15 @@ use rocket::data::{self, Data, FromData};
|
|||
use rocket::response::{self, Responder, content};
|
||||
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)]
|
||||
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.
|
||||
/// The JSON type: implements `FromData` and `Responder`, allowing you to easily
|
||||
/// consume and respond with JSON.
|
||||
///
|
||||
/// 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
|
||||
|
@ -122,42 +117,104 @@ impl<T> DerefMut for JSON<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// A nice little macro to create JSON serializable HashMaps, convenient for
|
||||
/// returning ad-hoc JSON messages.
|
||||
/// A macro to create ad-hoc JSON serializable values using JSON syntax.
|
||||
///
|
||||
/// 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.
|
||||
/// # Usage
|
||||
///
|
||||
/// To import the macro, add the `#[macro_use]` attribute to the `extern crate
|
||||
/// 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
|
||||
///
|
||||
/// ```
|
||||
/// Create a simple JSON object with two keys: `"username"` and `"id"`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused_variables)]
|
||||
/// # #[macro_use] extern crate rocket_contrib;
|
||||
/// # fn main() {
|
||||
/// let map = map! {
|
||||
/// "message" => "Done!",
|
||||
/// "success" => true,
|
||||
/// "count" => 3,
|
||||
/// };
|
||||
/// let value = json!({
|
||||
/// "username": "mjordan",
|
||||
/// "id": 23
|
||||
/// });
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// 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));
|
||||
/// Create a more complex object with a nested object and array:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![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_rules! map {
|
||||
($($key:expr => $value:expr),+) => ({
|
||||
use ::std::collections::HashMap;
|
||||
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),+)
|
||||
macro_rules! json {
|
||||
($($json:tt)+) => {
|
||||
json_internal!($($json)+)
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//! functionality commonly used by Rocket applications.
|
||||
|
@ -40,27 +40,29 @@
|
|||
#[cfg(feature = "lazy_static_macro")]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[cfg_attr(feature = "json", macro_use)]
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
#[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)]
|
||||
pub mod json;
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
pub use json::{JSON, SerdeError, Value};
|
||||
|
||||
#[cfg(feature = "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")]
|
||||
pub use templates::Template;
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
mod uuid;
|
||||
|
||||
#[cfg(feature = "uuid")]
|
||||
pub use uuid::{UUID, UuidParseError};
|
||||
|
|
|
@ -142,6 +142,7 @@ impl Template {
|
|||
///
|
||||
/// # context.insert("test", "test");
|
||||
/// let template = Template::render("index", &context);
|
||||
/// # assert_eq!(template.to_string(), "");
|
||||
/// ```
|
||||
pub fn render<S, T>(name: S, context: &T) -> Template
|
||||
where S: AsRef<str>, T: Serialize
|
||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
|||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
serde_derive = "0.8"
|
||||
serde = "0.9"
|
||||
serde_json = "0.9"
|
||||
serde_derive = "0.9"
|
||||
|
||||
[dev-dependencies]
|
||||
rocket = { path = "../../lib", features = ["testing"] }
|
||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
|||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
serde = "0.8"
|
||||
serde_derive = "0.8"
|
||||
serde_json = "0.8"
|
||||
serde = "0.9"
|
||||
serde_derive = "0.9"
|
||||
serde_json = "0.9"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
path = "../../contrib"
|
||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
|||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
serde_derive = "0.8"
|
||||
serde = "0.9"
|
||||
serde_json = "0.9"
|
||||
serde_derive = "0.9"
|
||||
lazy_static = "*"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
|
|
|
@ -16,9 +16,6 @@ use std::sync::Mutex;
|
|||
// The type to represent the ID of a message.
|
||||
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.
|
||||
lazy_static! {
|
||||
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.
|
||||
#[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.");
|
||||
if hashmap.contains_key(&id) {
|
||||
JSON(map!{
|
||||
"status" => "error",
|
||||
"reason" => "ID exists. Try put."
|
||||
})
|
||||
JSON(json!({
|
||||
"status": "error",
|
||||
"reason": "ID exists. Try put."
|
||||
}))
|
||||
} else {
|
||||
hashmap.insert(id, message.0.contents);
|
||||
JSON(map!{ "status" => "ok" })
|
||||
JSON(json!({ "status": "ok" }))
|
||||
}
|
||||
}
|
||||
|
||||
#[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();
|
||||
if hashmap.contains_key(&id) {
|
||||
hashmap.insert(id, message.0.contents);
|
||||
Some(JSON(map!{ "status" => "ok" }))
|
||||
Some(JSON(json!({ "status": "ok" })))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -68,11 +65,11 @@ fn get(id: ID) -> Option<JSON<Message>> {
|
|||
}
|
||||
|
||||
#[error(404)]
|
||||
fn not_found() -> JSON<SimpleMap> {
|
||||
JSON(map! {
|
||||
"status" => "error",
|
||||
"reason" => "Resource was not found."
|
||||
})
|
||||
fn not_found() -> JSON<Value> {
|
||||
JSON(json!({
|
||||
"status": "error",
|
||||
"reason": "Resource was not found."
|
||||
}))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
@ -6,9 +6,9 @@ workspace = "../../"
|
|||
[dependencies]
|
||||
rocket = { path = "../../lib" }
|
||||
rocket_codegen = { path = "../../codegen" }
|
||||
serde = "0.8"
|
||||
serde_json = "0.8"
|
||||
serde_derive = "0.8"
|
||||
serde = "0.9"
|
||||
serde_json = "0.9"
|
||||
serde_derive = "0.9"
|
||||
diesel = { version = "0.9", features = ["sqlite"] }
|
||||
diesel_codegen = { version = "0.9", features = ["sqlite"] }
|
||||
|
||||
|
|
Loading…
Reference in New Issue