3

我最近开始学习 Rust,目前正在尝试创建一个小型 API;我已经为 API 响应和错误的枚举创建了自己的结构:

// API Response Structure
pub struct ApiResponse {
    pub body: JsonValue,
    pub status: Status,
}

// Enum for my "custom errors"
#[derive(Debug, Snafu, Clone, Serialize)]
pub enum Errors {
    #[snafu(display("Unable to retrieve the specified entry."))]
    NotFound,

    #[snafu(display("Internal Server Error, unable to process the data."))]
    ISE,
}

然后我Responder<'_>为我的 API Response 结构实现了 trait:

impl<'r> Responder<'r> for ApiResponse {
    fn respond_to(self, req: &Request) -> Result<Response<'r>, Status> {
        Response::build_from(self.body.respond_to(req).unwrap())
            .status(self.status)
            .header(ContentType::JSON)
            .ok()
    }
}

但是,当我尝试使用提到的内容时,似乎我不能让我的函数返回 a Result<JsonValue, Errors>。我不太确定这个问题,也不是我对 Rust 的经验,所以任何文档/指针都将不胜感激。

这是返回响应类型的函数。

#[put("/users/<user_id>", format = "json", data = "<new_user>")]
pub fn update_user(
    conn: DbConnection,
    user_id: i32,
    new_user: Json<NewUser>,
) -> Result<JsonValue, ApiResponse> {

    match users::table.find(user_id).load::<User>(&*conn) {
        Ok(result) => {
            if result.len() < 1 {
                let response = ApiResponse {
                    body: json!({
                        "message": Errors::NotFound
                    }),
                    status: Status::NotFound
                };

                return Err(response)
            }
        },

        Err(e) => {
            let response = ApiResponse {
                body: json!({
                    "message": Errors::ISE
                }),
                status: Status::InternalServerError
            };

            return Err(response);
        },
    }

    match diesel::update(users::table.filter(id.eq(user_id)))
        .set((
            user_name.eq(new_user.user_name.to_string()),
            age.eq(new_user.age),
            gender.eq(new_user.gender.to_string()),
        ))
        .get_result::<User>(&*conn)
    {
        Ok(result) => Ok(json!(result)),
        Err(_) => {
            let res = ApiResponse {
                body: json!({
                    "message": Errors::ISE
                }),
                status: Status::InternalServerError
            };

            return Err(res);
        },
    }
}

旁注:请记住,我仍然是 Rust 的初学者,我的错误处理/代码一般不是最好的。


编辑:我忘了包括错误堆栈:

error[E0277]: the trait bound `std::result::Result<rocket_contrib::json::JsonValue, api_cont::ApiResponse>: rocket::response::Responder<'_>` is not satisfied
   --> src/routes.rs:72:6
    |
72  | ) -> Result<JsonValue, ApiResponse> {
    |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `rocket::response::Responder<'_>` is not implemented for `std::result::Result<rocket_contrib::json::JsonValue, api_cont::ApiResponse>`
    | 
   ::: /home/kenneth/.cargo/registry/src/github.com-1ecc6299db9ec823/rocket-0.4.4/src/handler.rs:202:20
    |
202 |     pub fn from<T: Responder<'r>>(req: &Request, responder: T) -> Outcome<'r> {
    |                    ------------- required by this bound in `rocket::handler::<impl rocket::Outcome<rocket::Response<'r>, rocket::http::Status, rocket::Data>>::from`
    |
    = help: the following implementations were found:
              <std::result::Result<R, E> as rocket::response::Responder<'r>>
              <std::result::Result<R, E> as rocket::response::Responder<'r>>
4

1 回答 1

5

我也遇到过这个错误。API Docs中提到了以下内容:

类型实现Responder应尽可能实现Debug特征。这是因为 for 的Responder实现Result需要它的Err类型来实现Debug。因此,Debug可以更容易地组合类型实现。

这意味着您必须实现 Debug,因为您将ApiResponse其用作Err类型。

#[derive(Debug)]
pub struct ApiResponse {
    pub body: JsonValue,
    pub status: Status,
}
于 2020-03-30T12:01:21.887 回答