Search code examples
jsonrustserderust-rocket

How to return JSON as a response in Rocket 0.5?


I'm trying to create a printing server in Rust using Rocket and face a problem when trying to send JSON as a response. The Rocket documentation shows that is really easy to send JSON as a response using the serde library.

Unfortunately, it isn't working for me:

#[derive(Serialize, Deserialize)]
pub struct Printers {
    pub printers: Vec<Printer>,
}

#[derive(Serialize, Deserialize)]
pub struct Printer {
    pub device_type: String,
    pub uid: String,
    pub provider: String,
    pub name: String,
    pub connection: String,
    pub version: u8,
    pub manufacturer: String,
}

#[get("/printers")]
fn printers(key: ApiKey<'_>) -> Json<Printers> {
    let resp = crate::get_printers::get();
    Json(resp)
}
error[E0277]: the trait bound `rocket_contrib::json::Json<order_route::Printers>: Responder<'_, '_>` is not satisfied
   --> src/order_route.rs:25:33
    |
25  | fn printers(key: ApiKey<'_>) -> Json<Printers> {
    |                                 ^^^^^^^^^^^^^^ the trait `Responder<'_, '_>` is not implemented for `rocket_contrib::json::Json<order_route::Printers>`
    |
note: required by `route::handler::<impl Outcome<rocket::Response<'o>, Status, rocket::Data<'o>>>::from`
   --> /home/*****/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.5.0-rc.1/src/route/handler.rs:188:5
    |
188 |     pub fn from<R: Responder<'r, 'o>>(req: &'r Request<'_>, responder: R) -> Outcome<'r> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0308]: mismatched types
  --> src/order_route.rs:27:10
   |
27 |     Json(resp)
   |          ^^^^ expected struct `order_route::Printers`, found enum `Result`
   |
   = note: expected struct `order_route::Printers`
                found enum `Result<structures::Printers, Box<dyn StdError>>`

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.
error: could not compile `hello` due to 2 previous errors

It seems I need a trait to do this, but don't know how to create it, If someone could help me to find a solution I will be grateful.

Here is my Cargo.toml:

[package]
name = "test"
version = "0.0.0"
edition = "2018"

[dependencies]
rocket = "0.5.0-rc.1"
reqwest = { version = "0.11", features = ["blocking", "json"] }
openssl = { version = "0.10", features = ["vendored"] }
json = "0.12.4"
serde = "1.0.127"
serde_json = "1.0.66"

[dependencies.rocket_contrib]
version = "0.4.10"
default-features = false
features = ["json"]

[workspace]
members = [
    ""
]

Solution

  • You are using rocket 0.5.0-rc.1 and rocket_contrib 0.4.10. While Json from rocket_contrib does implement Responder, it implements the Responder trait of Rocket v4, not that of Rocket v5.

    In Rocket v5, Json is not part of rocket_contib anymore, but included in the rocket crate (note that you need to enable the json feature on the rocket crate):

    use rocket::serde::json::Json;
    use serde::{Serialize, Deserialize};
    
    #[derive(Serialize, Deserialize)]
    pub struct Printers {
        pub printers: Vec<Printer>,
    }
    
    #[derive(Serialize, Deserialize)]
    pub struct Printer {
        pub device_type: String,
        pub uid: String,
        pub provider: String,
        pub name: String,
        pub connection: String,
        pub version: u8,
        pub manufacturer: String,
    }
    
    #[get("/printers")]
    fn printers() -> Json<Printers> {
        todo!();
    }
    

    Note that you can now also remove rocket_contrib from your Cargo.toml (as you are not using any features from it).