Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to make okapi comment rocket return Object #102

Closed
jiangxiaoqiang opened this issue Jun 10, 2022 · 1 comment
Closed

how to make okapi comment rocket return Object #102

jiangxiaoqiang opened this issue Jun 10, 2022 · 1 comment
Assignees

Comments

@jiangxiaoqiang
Copy link

jiangxiaoqiang commented Jun 10, 2022

I am using rust rocket as my web server, this is the code looks like:

/// # search the template list
///
/// return different type of template
#[openapi(tag = "template")]
#[get("/v1/list?<query..>")]
pub fn list(query: TemplateRequest) -> content::RawJson<String> {
    let contents = get_template_list(query.template_type, query.name);
    return box_rest_response(contents);
}

this code works fine. Now I facing a problem is that the rust rocket return raw json, the client side could not know the return content structure. it only show a json string in swagger:

enter image description here

the client did not know what the response content is. I have read the the rust rocket official document still did not figure out what should I do to return the entity structure. I have tried like this:

pub fn list(query: TemplateRequest) -> Result<Vec<TemplateResponse>, String> {
    let contents = get_template_list(query.template_type, query.name);
    return Ok(contents);
}

the compiler shows:

error[E0277]: the trait bound `std::vec::Vec<TemplateResponse>: Responder<'_, '_>` is not satisfied
  --> src/biz/template/bill_book_template_controller.rs:28:1
   |
28 | #[openapi(tag = "账本模版")]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Responder<'_, '_>` is not implemented for `std::vec::Vec<TemplateResponse>`
   |
   = help: the following implementations were found:
             <std::vec::Vec<u8> as Responder<'r, 'static>>
   = note: required because of the requirements on the impl of `Responder<'_, '_>` for `Result<std::vec::Vec<TemplateResponse>, std::string::String>`
note: required by a bound in `rocket_okapi::response::OpenApiResponder::responses`
  --> /Users/xiaoqiangjiang/.cargo/git/checkouts/okapi-727e9b4b9c217cbb/65244f0/rocket-okapi/src/response/mod.rs:10:41
   |
10 | pub trait OpenApiResponder<'a, 'r: 'a>: rocket::response::Responder<'a, 'r> {
   |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `rocket_okapi::response::OpenApiResponder::responses`
   = note: this error originates in the attribute macro `openapi` (in Nightly builds, run with -Z macro-backtrace for more info)

I also tried to implement like this:

impl<'r> Responder<'r, 'static> for Vec<TemplateResponse> {
    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
        // Convert object to json
        let body = serde_json::to_string(&self).unwrap();
        Response::build()
            .sized_body(body.len(), std::io::Cursor::new(body))
            .header(rocket::http::ContentType::JSON)
            .status(rocket::http::Status::new(self.http_status_code))
            .ok()
    }
}

seems did not work. I have tried this:

pub fn list(query: TemplateRequest) -> Result<content::RawJson<String>, String> {
    let contents = get_template_list(query.template_type, query.name);
    return Ok(box_rest_response(contents));
}

it works but still could not show the response structure at client side.

@ralpha
Copy link
Collaborator

ralpha commented Jun 11, 2022

The easiest way to return JSON is to use Json<...> with a struct.
For example:

/// # Create post using query params
///
/// Returns the created post.
#[openapi(tag = "Posts")]
#[get("/post_by_query?<post..>")]
fn create_post_by_query(post: Post) -> Option<Json<Post>> {
Some(Json(post))
}

Then you can add the structure and documentation like this:
#[derive(Serialize, Deserialize, JsonSchema, FromForm)]
struct Post {
/// The unique identifier for the post.
post_id: u64,
/// The title of the post.
title: String,
/// A short summary of the post.
summary: Option<String>,
}

With RawJson you can return any JSON, so there is no way to know what the structure is of the JSON at compile time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants