How to create common HTTP Response examples in utoipa (Swagger)

I'm using utoipa in order to document my REST API but I have to duplicate my code with same error messages (401 and 403) like this example

#[utoipa::path(
    context_path = "/user",
    tag = "user",
    responses(
        (status = 200, description = "Endpoint to get all data from a user.",
            body = Value,
            example = json!({
                "id": 12,
                "user_id": "TestUser42",
                "class": "8a",
                "created_at": "07-04-2004",
                "user_data": {
                    "traffic": [],
                    "modules": []
                }
            })
        ),
        (status = 401, description = "Access token is missing or invalid",
            body = HttpError,
            example = json!({
                "time": "07-05-2024 08:17:33",
                "status_code": "401",
                "error_type": "Unauthorized",
                "reason": "Access token is missing or invalid"
            })
        ),
        (status = 404, description = "ID not found", body = HttpError,
            example = json!({
                "time": "07-05-2024 08:17:33",
                "status_code": "404",
                "error_type": "NotFound",
                "reason": "ID not found"
            })
        ),
        (status = 403, description = "Not allowed to call this endpoint with the current permission", body = HttpError,
            example = json!({
                "time": "07-05-2024 08:17:33",
                "status_code": "403",
                "error_type": "AccessForbidden",
                "reason": "Wrong or missing permissions"
            })
        )
    ),
    security(
        ("bearerAuth" = [])
    )
)]
#[get("/get")]
#[protect(any("STUDENT", "ADMIN"), error = "access_denied")]
pub async fn get_user(
    claims: Option<web::ReqData<Claims>>
) -> impl Responder {

    if let Some(claims) = claims {
        match user_service::get_user(claims.sub.parse::<i32>().unwrap()).await {
            Ok(u) => HttpResponse::Ok().json(u),
            Err(_) => HttpError::not_found("User does not exist").error_response()
        }
    } else {
        HttpError::bad_gateway("Unable to get user").error_response()
    }
}

How is it possible to use IntoResponses or reading the responses from a JSON file? IntoResponses works but it isn't possible to create examples like I want it similar to my code. There is no function that allows me to create an example (i.e. example(json!({})) which does not exists). There is an ExampleBuilder::new() but I can't use it or doesn't know where.

impl IntoResponses for HttpError {
    fn responses() -> BTreeMap<String, RefOr<Response>> {
        ResponsesBuilder::new()
            .response("401", ResponseBuilder::new()
                .description("JWT invalid or missing")
                .content("application/json",
                         Content::new(HttpError {
                             time: "07-05-2024 08:17:33".to_string(),
                             status_code: "401".to_string(),
                             error_type: ErrorResponse::Unauthorized,
                             reason: Some("JWT missing or invalid".to_string()),
                         }))
            )
            .response("403", ResponseBuilder::new()
                .description("Not allowed to call this endpoint with the current permission")
                .content("application/json",
                         Content::new(HttpError {
                             time: "07-05-2024 08:17:33".to_string(),
                             status_code: "403".to_string(),
                             error_type: ErrorResponse::Forbidden,
                             reason: Some("Access Forbidden".to_string()),
                         }))
            )
            .build()
            .into()
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.