如何使用自动字段反序列化在 Rust Rocket 中返回 JSON 作为响应?

Dir*_*ear 4 json rust rocket

我正在尝试使用 Rust 创建打印服务器,并在尝试发送 JSON 作为响应时遇到问题。

我在 Rocket 文档中发现发送 JSON 作为响应非常容易:您只需使用 Serde 库即可。

不幸的是,这对我来说并不是那么简单......

这是我当前的代码:

#[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,
}

/**
 * Here is my main problem 
 *   -> I want to send back the Printers Object as a JSON
 */
#[get("/printers")]
fn printers(key: ApiKey<'_>) -> Json<Printers> {
    let resp = crate::get_printers::get();
    Json(resp)
}
Run Code Online (Sandbox Code Playgroud)

这是错误代码:

   --> 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`
   --> ********/.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> {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

看来我需要一个trait来做到这一点,但不知道如何创建它,如果有人可以帮助我找到解决方案,我将不胜感激。

[编辑]

这是 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 = [
    ""
]
Run Code Online (Sandbox Code Playgroud)

这是完整的堆栈跟踪

[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 = [
    ""
]
Run Code Online (Sandbox Code Playgroud)

sk_*_*ant 6

您正在使用 Rocket 0.5.0-rc.1 和 Rocket_contrib 0.4.10。虽然Jsonfrom Rocket_contrib确实实现了Responder,但它实现了ResponderRocket v4 的特征,而不是 Rocket v5 的特征。

在 Rocket v5 中,Json不再是其中的一部分rocket_contib,而是包含在rocketcrate 中(请注意,您需要在 cratejson上启用该功能rocket):

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!();
}
Run Code Online (Sandbox Code Playgroud)

请注意,您现在还可以rocket_contrib从 Cargo.toml 中删除(因为您没有使用其中的任何功能)。

  • 再次感谢您的反馈,我同时在搜索并在 Rocket 文档中找到了规格,我在这里为那些遇到同样问题的人留下了链接 [JSON 导入的 Rocket 文档链接](https://api. Rocket.rs/master/rocket/index.html)!你让我很开心:D (2认同)

小智 6

任何觉得困难的人,这里有解决方案:

  • 在文件中启用Rocket Rust 的JSON功能Cargo.toml

    [package]
    #...
    
    [dependencies.rocket]
    version = "0.5.0-rc.1"
    features = ["json"]
    
    [dependencies.serde]
    version = "1.0.136"
    features = ["derive"]
    
    [dependencies]
    #...
    
    # rocket_contrib not required anymore
    
    Run Code Online (Sandbox Code Playgroud)
  • 在你的src/main.rs文件中

    [package]
    #...
    
    [dependencies.rocket]
    version = "0.5.0-rc.1"
    features = ["json"]
    
    [dependencies.serde]
    version = "1.0.136"
    features = ["derive"]
    
    [dependencies]
    #...
    
    # rocket_contrib not required anymore
    
    Run Code Online (Sandbox Code Playgroud)
  • 使用 cURL 测试 API

    // rocket v0.5.0-rc.1
    use rocket::{
       self,
       serde::{json::Json, Deserialize, Serialize},
    };
    
    #[derive(Deserialize, Serialize)]
    struct User {
       name: String,
       age: u8,
    }
    
    #[rocket::post("/post", format = "json", data = "<user>")]
    fn post_data(user: Json<User>) -> Json<User> {
       let name: String = user.name.clone();
       let age: u8 = user.age.clone();
    
       Json(User { name, age })
    }
    
    #[rocket::main]
    async fn main() {
       if let Err(err) = rocket::build()
          .mount("/", rocket::routes![post_data])
          .launch()
          .await
       {
          println!("Rocket Rust couldn't take off successfully!");
          drop(err); // Drop initiates Rocket-formatted panic
       }
    }
    
    Run Code Online (Sandbox Code Playgroud)