如何使用自动字段反序列化 return JSON 作为 Rust Rocket 中的响应?
How to return JSON as a response in Rust Rocket with auto field deserialising?
我正在尝试创建一个生锈的打印服务器,但在尝试发送 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)
}
这是错误代码:
--> 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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
看来我需要一个 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 = [
""
]
这是完整的堆栈跟踪
*****:~/*****/label-printer-server-rust/server$ cargo run
Compiling hello v0.0.0 (/home/*****/*****/label-printer-server-rust/server)
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
您正在使用 rocket 0.5.0-rc.1 和 rocket_contrib 0.4.10。 Json
来自 rocket_contrib does implement Responder
,它实现了 Rocket v4 的 Responder
特性,而不是 Rocket v5 的特性。
在 Rocket v5 中,Json
不再是 rocket_contib
的一部分,而是包含在 rocket
crate 中(请注意,您需要启用 json
功能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!();
}
请注意,您现在还可以从 Cargo.toml 中删除 rocket_contrib
(因为您没有使用它的任何功能)。
我想补充一下评论中提到的 Elias 的回答:
在您的 cargo.toml
中,您需要启用 JSON 功能:
[dependencies]
## SEE HERE!!
rocket = {version ="0.5.0-rc.1", features=["json"]}
# other properties omitted for brevity
# You can remove this!! Rocket Contrib doesn't exist in Rocket V0.5
#[dependencies.rocket_contrib]
#version = "0.4.10"
#default-features = false
#features = ["json"]
任何遇到困难的人,这里是解决方案:
在您的Cargo.toml
文件
中启用JSON火箭锈蚀功能
[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
在您的 src/main.rs
文件中
// 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
}
}
使用 cURL
测试 API
curl -d '{"age": 12,"name":"John Doe"}' -H 'Content-Type: application/json'
http://localhost:8000/post
# Response
# {"name":"John Doe","age":12}
我正在尝试创建一个生锈的打印服务器,但在尝试发送 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)
}
这是错误代码:
--> 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> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
看来我需要一个 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 = [
""
]
这是完整的堆栈跟踪
*****:~/*****/label-printer-server-rust/server$ cargo run
Compiling hello v0.0.0 (/home/*****/*****/label-printer-server-rust/server)
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
您正在使用 rocket 0.5.0-rc.1 和 rocket_contrib 0.4.10。 Json
来自 rocket_contrib does implement Responder
,它实现了 Rocket v4 的 Responder
特性,而不是 Rocket v5 的特性。
在 Rocket v5 中,Json
不再是 rocket_contib
的一部分,而是包含在 rocket
crate 中(请注意,您需要启用 json
功能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!();
}
请注意,您现在还可以从 Cargo.toml 中删除 rocket_contrib
(因为您没有使用它的任何功能)。
我想补充一下评论中提到的 Elias 的回答:
在您的 cargo.toml
中,您需要启用 JSON 功能:
[dependencies]
## SEE HERE!!
rocket = {version ="0.5.0-rc.1", features=["json"]}
# other properties omitted for brevity
# You can remove this!! Rocket Contrib doesn't exist in Rocket V0.5
#[dependencies.rocket_contrib]
#version = "0.4.10"
#default-features = false
#features = ["json"]
任何遇到困难的人,这里是解决方案:
在您的
中启用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
在您的
src/main.rs
文件中// 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 } }
使用 cURL
测试 APIcurl -d '{"age": 12,"name":"John Doe"}' -H 'Content-Type: application/json' http://localhost:8000/post # Response # {"name":"John Doe","age":12}