juhaku / utoipa

Simple, Fast, Code first and Compile time generated OpenAPI documentation for Rust
Apache License 2.0
2.21k stars 170 forks source link

Feature request: support `#[schema(skip)]` #795

Open magurotuna opened 10 months ago

magurotuna commented 10 months ago

Requested feature

Add support for #[schema(skip)]

What this does

When this attribute is present, the target field or variant will not show up in the generated OpenAPI spec. This is like #[serde(skip)], but the difference is that the proposed attribute doesn't affect how it is serialized.

Background

We're using utoipa to generate OpenAPI spec based on API implementation written in Rust. One unique point with our API is that it's used both externally and internally; for external users, the API must not make breaking changes while for internal purposes we may make some changes that can be breaking. In order to achieve it, we use structs like below, which has __internal field that appears in the response body only if the request was made by an internal client.

#[derive(utoipa::ToSchema, Serailize)]
struct MyResponse {
    /// This is public to all users
    public_value: i32,
    /// This is set to `Some` only when responding to internal clients
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    ___secret: Option<SecretStuff>,
}

#[derive(Serialize)]
struct SecretStuff {
    secret_value: String,
}

So essentially we would like to use SecretStuff as a schema, but we don't want it to show up in the OpenAPI spec because our OpenAPI spec serves as a public documentation of stable interfaces.

With #[schema(skip)], this would be accomplished by just adding this attribute to __secret, like:

#[derive(utoipa::ToSchema, Serailize)]
struct MyResponse {
    /// This is public to all users
    public_value: i32,
    /// This is set to `Some` only when responding to internal clients
    #[serde(flatten, skip_serializing_if = "Option::is_none")]
    #[schema(skip)]
    ___secret: Option<SecretStuff>,
}

#[derive(Serialize)]
struct SecretStuff {
    secret_value: String,
}
juhaku commented 10 months ago

@magurotuna Sure, sounds a good idea, adding this kind of support should be quite easily done. Though I would make it as #[schema(ignore)] so it will not be confused with the #[serde(skip)]. The reasoning for this is that there currently are some schema attributes that are synomuous to serde attributes and if this is added but it behaves differently to the serde counterparts it will be confusing to the users. Thus #[schema(ignore)] to ignore attribute from the schema and #[serde(skip)] to skip the de/serialization. Then this would even allow defining support for #[schema(skip)] that would behave like #[serde(skip)] if needed.

GodTamIt commented 5 months ago

I ran into a similar use case today. #[param(ignore)] would also be quite useful

Narayanbhat166 commented 3 months ago

Have a similar use case. @juhaku can I pick this up if this has not been implemented yet?

GeeWee commented 1 month ago

I also have a similar use-case, where we e.g. use #[serde(flatten) on a recursive data-type, which I'd prefer to just skip adding to the openAPI spec entirely. I can't skip it with serde as I still want it to be serialized, just not documented.

juhaku commented 2 weeks ago

@Narayanbhat166 This has not been yet started working on, So please if there is time an energy, all contributions are welcome 🙂