utoipa

Derive Macro ToResponse

source
#[derive(ToResponse)]
{
    // Attributes available to this derive:
    #[response]
    #[content]
    #[to_schema]
}
Expand description

Generate reusable OpenAPI response what can be used in utoipa::path or in OpenApi.

This is #[derive] implementation for ToResponse trait.

#[response] attribute can be used to alter and add response attributes.

#[content] attributes is used to make enum variant a content of a specific type for the response.

#[to_schema] attribute is used to inline a schema for a response in unnamed structs or enum variants with #[content] attribute. Note! ToSchema need to be implemented for the field or variant type.

Type derived with ToResponse uses provided doc comment as a description for the response. It can alternatively be overridden with description = ... attribute.

ToResponse can be used in four different ways to generate OpenAPI response component.

  1. By decorating struct or enum with ToResponse derive macro. This will create a response with inlined schema resolved from the fields of the struct or variants of the enum.

     #[derive(ToResponse)]
     #[response(description = "Person response returns single Person entity")]
     struct Person {
         name: String,
     }
  2. By decorating unnamed field struct with ToResponse derive macro. Unnamed field struct allows users to use new type pattern to define one inner field which is used as a schema for the generated response. This allows users to define Vec and Option response types. Additionally these types can also be used with #[to_schema] attribute to inline the field’s type schema if it implements ToSchema derive macro.

     /// Person list response
     #[derive(utoipa::ToResponse)]
     struct PersonList(Vec<Person>);
  3. By decorating unit struct with ToResponse derive macro. Unit structs will produce a response without body.

     /// Success response which does not have body.
     #[derive(utoipa::ToResponse)]
     struct SuccessResponse;
  4. By decorating enum with variants having #[content(...)] attribute. This allows users to define multiple response content schemas to single response according to OpenAPI spec. Note! Enum with content attribute in variants cannot have enum level example or examples defined. Instead examples need to be defined per variant basis. Additionally these variants can also be used with #[to_schema] attribute to inline the variant’s type schema if it implements ToSchema derive macro.

     #[derive(utoipa::ToSchema)]
     struct Admin {
         name: String,
     }
     #[derive(utoipa::ToSchema)]
     struct Admin2 {
         name: String,
         id: i32,
     }
    
     #[derive(utoipa::ToResponse)]
     enum Person {
         #[response(examples(
             ("Person1" = (value = json!({"name": "name1"}))),
             ("Person2" = (value = json!({"name": "name2"})))
         ))]
         Admin(#[content("application/vnd-custom-v1+json")] Admin),
    
         #[response(example = json!({"name": "name3", "id": 1}))]
         Admin2(#[content("application/vnd-custom-v2+json")] #[to_schema] Admin2),
     }

§ToResponse #[response(...)] attributes

  • description = "..." Define description for the response as str. This can be used to override the default description resolved from doc comments if present.

  • content_type = "..." | content_type = [...] Can be used to override the default behavior of auto resolving the content type from the body attribute. If defined the value should be valid content type such as application/json. By default the content type is text/plain for primitive Rust types, application/octet-stream for [u8] and application/json for struct and complex enum types. Content type can also be slice of content_type values if the endpoint support returning multiple response content types. E.g ["application/json", "text/xml"] would indicate that endpoint can return both json and xml formats. The order of the content types define the default example show first in the Swagger UI. Swagger UI wil use the first content_type value as a default example.

  • headers(...) Slice of response headers that are returned back to a caller.

  • example = ... Can be json!(...). json!(...) should be something that serde_json::json! can parse as a serde_json::Value.

  • examples(...) Define multiple examples for single response. This attribute is mutually exclusive to the example attribute and if both are defined this will override the example.

    • name = ... This is first attribute and value must be literal string.
    • summary = ... Short description of example. Value must be literal string.
    • description = ... Long description of example. Attribute supports markdown for rich text representation. Value must be literal string.
    • value = ... Example value. It must be json!(...). json!(...) should be something that serde_json::json! can parse as a serde_json::Value.
    • external_value = ... Define URI to literal example value. This is mutually exclusive to the value attribute. Value must be literal string.

    Example of example definition.

     ("John" = (summary = "This is John", value = json!({"name": "John"})))

§Examples

Use reusable response in operation handler.

#[derive(utoipa::ToResponse)]
struct PersonResponse {
   value: String
}

#[derive(utoipa::OpenApi)]
#[openapi(components(responses(PersonResponse)))]
struct Doc;

#[utoipa::path(
    get,
    path = "/api/person",
    responses(
        (status = 200, response = PersonResponse)
    )
)]
fn get_person() -> PersonResponse {
    PersonResponse { value: "person".to_string() }
}

Create a response from named struct.

 /// This is description
 ///
 /// It will also be used in `ToSchema` if present
 #[derive(utoipa::ToSchema, utoipa::ToResponse)]
 #[response(
     description = "Override description for response",
     content_type = "text/xml"
 )]
 #[response(
     example = json!({"name": "the name"}),
     headers(
         ("csrf-token", description = "response csrf token"),
         ("random-id" = i32)
     )
 )]
 struct Person {
     name: String,
 }

Create inlined person list response.

 /// Person list response
 #[derive(utoipa::ToResponse)]
 struct PersonList(#[to_schema] Vec<Person>);

Create enum response from variants.

 #[derive(utoipa::ToResponse)]
 enum PersonType {
     Value(String),
     Foobar,
 }