utoipa_gen

Derive Macro ToSchema

Source
#[derive(ToSchema)]
{
    // Attributes available to this derive:
    #[schema]
}
Expand description

Generate reusable OpenAPI schema to be used together with OpenApi.

This is #[derive] implementation for ToSchema trait. The macro accepts one schema attribute optionally which can be used to enhance generated documentation. The attribute can be placed at item level or field and variant levels in structs and enum.

You can use the Rust’s own #[deprecated] attribute on any struct, enum or field to mark it as deprecated and it will reflect to the generated OpenAPI spec.

#[deprecated] attribute supports adding additional details such as a reason and or since version but this is is not supported in OpenAPI. OpenAPI has only a boolean flag to determine deprecation. While it is totally okay to declare deprecated with reason #[deprecated = "There is better way to do this"] the reason would not render in OpenAPI spec.

Doc comments on fields will resolve to field descriptions in generated OpenAPI doc. On struct level doc comments will resolve to object descriptions.

Schemas derived with ToSchema will be automatically collected from usage. In case of looping schema tree no_recursion attribute must be used to break from recurring into infinite loop. See more details from example. All arguments of generic schemas must implement ToSchema trait.

/// This is a pet
#[derive(utoipa::ToSchema)]
struct Pet {
    /// Name for your pet
    name: String,
}

§Named Field Struct Optional Configuration Options for #[schema(...)]

  • description = ... Can be literal string or Rust expression e.g. const reference or include_str!(...) statement. This can be used to override default description what is resolved from doc comments of the type.
  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • xml(...) Can be used to define Xml object properties applicable to Structs.
  • title = ... Literal string value. Can be used to define title for struct in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the struct.
  • rename_all = ... Supports same syntax as serde rename_all attribute. Will rename all fields of the structs accordingly. If both serde rename_all and schema rename_all are defined serde will take precedence.
  • as = ... Can be used to define alternative path and name for the schema what will be used in the OpenAPI. E.g as = path::to::Pet. This would make the schema appear in the generated OpenAPI spec as path.to.Pet. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.
  • bound = ... Can be used to override default trait bounds on generated impls. See Generic schemas section below for more details.
  • default Can be used to populate default values on all fields using the struct’s Default implementation.
  • deprecated Can be used to mark all fields as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the fields as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.
  • max_properties = ... Can be used to define maximum number of properties this struct can contain. Value must be a number.
  • min_properties = ... Can be used to define minimum number of properties this struct can contain. Value must be a number.
  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic. On struct level the no_recursion rule will be applied to all of its fields.

§Named Fields Optional Configuration Options for #[schema(...)]

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • default = ... Can be any value e.g. literal, method reference or json!(...).
  • format = ... May either be variant of the KnownFormat enum, or otherwise an open value as a string. By default the format is derived from the type of the property according OpenApi spec.
  • write_only Defines property is only used in write operations POST,PUT,PATCH but not in GET
  • read_only Defines property is only used in read operations GET but not in POST,PUT,PATCH
  • xml(...) Can be used to define Xml object properties applicable to named fields. See configuration options at xml attributes of ToSchema
  • value_type = ... Can be used to override default type derived from type of the field used in OpenAPI spec. This is useful in cases where the default type does not correspond to the actual type e.g. when any third-party types are used which are not ToSchemas nor primitive types. The value can be any Rust type what normally could be used to serialize to JSON, or either virtual type Object or Value. Object will be rendered as generic OpenAPI object (type: object). Value will be rendered as any OpenAPI value (i.e. no type restriction).
  • inline If the type of this field implements ToSchema, then the schema definition will be inlined. warning: Don’t use this for recursive data types!
  • required = ... Can be used to enforce required status for the field. See rules
  • nullable Defines property is nullable (note this is different to non-required).
  • rename = ... Supports same syntax as serde rename attribute. Will rename field accordingly. If both serde rename and schema rename are defined serde will take precedence.
  • multiple_of = ... Can be used to define multiplier for a value. Value is considered valid division will result an integer. Value must be strictly above 0.
  • maximum = ... Can be used to define inclusive upper bound to a number value.
  • minimum = ... Can be used to define inclusive lower bound to a number value.
  • exclusive_maximum = ... Can be used to define exclusive upper bound to a number value.
  • exclusive_minimum = ... Can be used to define exclusive lower bound to a number value.
  • max_length = ... Can be used to define maximum length for string types.
  • min_length = ... Can be used to define minimum length for string types.
  • pattern = ... Can be used to define valid regular expression in ECMA-262 dialect the field value must match.
  • max_items = ... Can be used to define maximum items allowed for array fields. Value must be non-negative integer.
  • min_items = ... Can be used to define minimum items allowed for array fields. Value must be non-negative integer.
  • schema_with = ... Use schema created by provided function reference instead of the default derived schema. The function must match to fn() -> Into<RefOr<Schema>>. It does not accept arguments and must return anything that can be converted into RefOr<Schema>.
  • additional_properties = ... Can be used to define free form types for maps such as HashMap and BTreeMap. Free form type enables use of arbitrary types within map values. Supports formats additional_properties and additional_properties = true.
  • deprecated Can be used to mark the field as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the field as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.
  • content_encoding = ... Can be used to define content encoding used for underlying schema object. See Object::content_encoding
  • content_media_type = ... Can be used to define MIME type of a string for underlying schema object. See [Object::content_media_type][schema_object_`media_type]
  • ignore or ignore = ... Can be used to skip the field from being serialized to OpenAPI schema. It accepts either a literal bool value or a path to a function that returns bool (Fn() -> bool).
  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic.
§Field nullability and required rules

Field is considered required if

  • it is not Option field
  • and it does not have skip_serializing_if property
  • and it does not have serde_with double_option
  • and it does not have default value provided with serde default attribute

Field is considered nullable when field type is Option.

§Xml attribute Configuration Options

  • xml(name = "...") Will set name for property or type.
  • xml(namespace = "...") Will set namespace for xml element which needs to be valid uri.
  • xml(prefix = "...") Will set prefix for name.
  • xml(attribute) Will translate property to xml attribute instead of xml element.
  • xml(wrapped) Will make wrapped xml element.
  • xml(wrapped(name = "wrap_name")) Will override the wrapper elements name.

See Xml for more details.

§Unnamed Field Struct Optional Configuration Options for #[schema(...)]

  • description = ... Can be literal string or Rust expression e.g. const reference or include_str!(...) statement. This can be used to override default description what is resolved from doc comments of the type.
  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • default = ... Can be any value e.g. literal, method reference or json!(...). If no value is specified, and the struct has only one field, the field’s default value in the schema will be set from the struct’s Default implementation.
  • format = ... May either be variant of the KnownFormat enum, or otherwise an open value as a string. By default the format is derived from the type of the property according OpenApi spec.
  • value_type = ... Can be used to override default type derived from type of the field used in OpenAPI spec. This is useful in cases where the default type does not correspond to the actual type e.g. when any third-party types are used which are not ToSchemas nor primitive types. The value can be any Rust type what normally could be used to serialize to JSON or either virtual type Object or Value. Object will be rendered as generic OpenAPI object (type: object). Value will be rendered as any OpenAPI value (i.e. no type restriction).
  • title = ... Literal string value. Can be used to define title for struct in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the struct.
  • as = ... Can be used to define alternative path and name for the schema what will be used in the OpenAPI. E.g as = path::to::Pet. This would make the schema appear in the generated OpenAPI spec as path.to.Pet. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.
  • bound = ... Can be used to override default trait bounds on generated impls. See Generic schemas section below for more details.
  • deprecated Can be used to mark the field as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the field as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.
  • content_encoding = ... Can be used to define content encoding used for underlying schema object. See Object::content_encoding
  • content_media_type = ... Can be used to define MIME type of a string for underlying schema object. See Object::content_media_type
  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic.

§Enum Optional Configuration Options for #[schema(...)]

§Plain Enum having only Unit variants Optional Configuration Options for #[schema(...)]

  • description = ... Can be literal string or Rust expression e.g. const reference or include_str!(...) statement. This can be used to override default description what is resolved from doc comments of the type.
  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • default = ... Can be any value e.g. literal, method reference or json!(...).
  • title = ... Literal string value. Can be used to define title for enum in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the enum.
  • rename_all = ... Supports same syntax as serde rename_all attribute. Will rename all variants of the enum accordingly. If both serde rename_all and schema rename_all are defined serde will take precedence.
  • as = ... Can be used to define alternative path and name for the schema what will be used in the OpenAPI. E.g as = path::to::Pet. This would make the schema appear in the generated OpenAPI spec as path.to.Pet. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.
  • bound = ... Can be used to override default trait bounds on generated impls. See Generic schemas section below for more details.
  • deprecated Can be used to mark the enum as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the enum as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.

§Plain Enum Variant Optional Configuration Options for #[schema(...)]

  • rename = ... Supports same syntax as serde rename attribute. Will rename variant accordingly. If both serde rename and schema rename are defined serde will take precedence. Note! Repr enum variant does not support rename.

§Mixed Enum Optional Configuration Options for #[schema(...)]

  • description = ... Can be literal string or Rust expression e.g. const reference or include_str!(...) statement. This can be used to override default description what is resolved from doc comments of the type.

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.

  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each

  • default = ... Can be any value e.g. literal, method reference or json!(...).

  • title = ... Literal string value. Can be used to define title for enum in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the enum.

  • rename_all = ... Supports same syntax as serde rename_all attribute. Will rename all variants of the enum accordingly. If both serde rename_all and schema rename_all are defined serde will take precedence.

  • as = ... Can be used to define alternative path and name for the schema what will be used in the OpenAPI. E.g as = path::to::Pet. This would make the schema appear in the generated OpenAPI spec as path.to.Pet. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.

  • bound = ... Can be used to override default trait bounds on generated impls. See Generic schemas section below for more details.

  • deprecated Can be used to mark the enum as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the enum as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.

  • discriminator = ... or discriminator(...) Can be used to define OpenAPI discriminator field for enums with single unnamed ToSchema reference field. See the discriminator syntax.

  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic. On enum level the no_recursion rule will be applied to all of its variants.

    §#[schema(discriminator)] syntax

    Discriminator can only be used with enums having #[serde(untagged)] attribute and each variant must have only one unnamed field schema reference to type implementing ToSchema.

    Simple form discriminator = ...

    Can be literal string or expression e.g. const reference. It can be defined as discriminator = "value" where the assigned value is the discriminator field that must exists in each variant referencing schema.

Complex form discriminator(...)

  • property_name = ... Can be literal string or expression e.g. const reference.
  • mapping key Can be literal string or expression e.g. const reference.
  • mapping value Can be literal string or expression e.g. const reference.

Additionally discriminator can be defined with custom mappings as show below. The mapping values defines key = value pairs where key is the expected value for property_name field and value is schema to map.

discriminator(property_name = "my_field", mapping(
     ("value" = "#/components/schemas/Schema1"),
     ("value2" = "#/components/schemas/Schema2")
))

§Mixed Enum Named Field Variant Optional Configuration Options for #[serde(schema)]

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each
  • default = ... Can be any value e.g. literal, method reference or json!(...).
  • title = ... Literal string value. Can be used to define title for enum variant in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the enum.
  • xml(...) Can be used to define Xml object properties applicable to Structs.
  • rename = ... Supports same syntax as serde rename attribute. Will rename variant accordingly. If both serde rename and schema rename are defined serde will take precedence.
  • rename_all = ... Supports same syntax as serde rename_all attribute. Will rename all variant fields accordingly. If both serde rename_all and schema rename_all are defined serde will take precedence.
  • deprecated Can be used to mark the enum as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the enum as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.
  • max_properties = ... Can be used to define maximum number of properties this struct can contain. Value must be a number.
  • min_properties = ... Can be used to define minimum number of properties this struct can contain. Value must be a number.
  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic. On named field variant level the no_recursion rule will be applied to all of its fields.

§Mixed Enum Unnamed Field Variant Optional Configuration Options for #[serde(schema)]

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • default = ... Can be any value e.g. literal, method reference or json!(...).
  • title = ... Literal string value. Can be used to define title for enum variant in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the struct.
  • rename = ... Supports same syntax as serde rename attribute. Will rename variant accordingly. If both serde rename and schema rename are defined serde will take precedence.
  • format = ... May either be variant of the KnownFormat enum, or otherwise an open value as a string. By default the format is derived from the type of the property according OpenApi spec.
  • value_type = ... Can be used to override default type derived from type of the field used in OpenAPI spec. This is useful in cases where the default type does not correspond to the actual type e.g. when any third-party types are used which are not ToSchemas nor primitive types. The value can be any Rust type what normally could be used to serialize to JSON or either virtual type Object or Value. Object will be rendered as generic OpenAPI object (type: object). Value will be rendered as any OpenAPI value (i.e. no type restriction).
  • deprecated Can be used to mark the field as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the field as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.
  • no_recursion Is used to break from recursion in case of looping schema tree e.g. Pet -> Owner -> Pet. no_recursion attribute must be used within Ower type not to allow recurring into Pet. Failing to do so will cause infinite loop and runtime panic.
§Mixed Enum Unnamed Field Variant’s Field Configuration Options
  • inline If the type of this field implements ToSchema, then the schema definition will be inlined. warning: Don’t use this for recursive data types!

    Inline unnamed field variant schemas.

     #[derive(ToSchema)]
     enum Card {
         Number(#[schema(inline)] Number),
         Color(#[schema(inline)] Color),
     }

§Mixed Enum Unit Field Variant Optional Configuration Options for #[serde(schema)]

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • title = ... Literal string value. Can be used to define title for enum variant in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the struct.
  • rename = ... Supports same syntax as serde rename attribute. Will rename variant accordingly. If both serde rename and schema rename are defined serde will take precedence.
  • deprecated Can be used to mark the field as deprecated in the generated OpenAPI spec but not in the code. If you’d like to mark the field as deprecated in the code as well use Rust’s own #[deprecated] attribute instead.

§Partial #[serde(...)] attributes support

ToSchema derive has partial support for serde attributes. These supported attributes will reflect to the generated OpenAPI doc. For example if #[serde(skip)] is defined the attribute will not show up in the OpenAPI spec at all since it will not never be serialized anyway. Similarly the rename and rename_all will reflect to the generated OpenAPI doc.

  • rename_all = "..." Supported at the container level.
  • rename = "..." Supported only at the field or variant level.
  • skip = "..." Supported only at the field or variant level.
  • skip_serializing = "..." Supported only at the field or variant level.
  • skip_deserializing = "..." Supported only at the field or variant level.
  • skip_serializing_if = "..." Supported only at the field level.
  • with = ... Supported only at field level.
  • tag = "..." Supported at the container level.
  • content = "..." Supported at the container level, allows adjacently-tagged enums. This attribute requires that a tag is present, otherwise serde will trigger a compile-time failure.
  • untagged Supported at the container level. Allows untagged enum representation.
  • default Supported at the container level and field level according to serde attributes.
  • deny_unknown_fields Supported at the container level.
  • flatten Supported at the field level.

Other serde attributes works as is but does not have any effect on the generated OpenAPI doc.

Note! tag attribute has some limitations like it cannot be used with tuple types. See more at enum representation docs.

Note! with attribute is used in tandem with serde_with to recognize double_option from field value. double_option is only supported attribute from serde_with crate.

#[derive(Serialize, ToSchema)]
struct Foo(String);

#[derive(Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
enum Bar {
    UnitValue,
    #[serde(rename_all = "camelCase")]
    NamedFields {
        #[serde(rename = "id")]
        named_id: &'static str,
        name_list: Option<Vec<String>>
    },
    UnnamedFields(Foo),
    #[serde(skip)]
    SkipMe,
}

Add custom tag to change JSON representation to be internally tagged.

#[derive(Serialize, ToSchema)]
struct Foo(String);

#[derive(Serialize, ToSchema)]
#[serde(tag = "tag")]
enum Bar {
    UnitValue,
    NamedFields {
        id: &'static str,
        names: Option<Vec<String>>
    },
}

Add serde default attribute for MyValue struct. Similarly default could be added to individual fields as well. If default is given the field’s affected will be treated as optional.

 #[derive(utoipa::ToSchema, serde::Deserialize, Default)]
 #[serde(default)]
 struct MyValue {
     field: String
 }

§#[repr(...)] attribute support

Serde repr allows field-less enums be represented by their numeric value.

  • repr(u*) for unsigned integer.
  • repr(i*) for signed integer.

Supported schema attributes

  • example = ... Can be any value e.g. literal, method reference or json!(...). Deprecated since OpenAPI 3.0, using examples is preferred instead.
  • examples(..., ...) Comma separated list defining multiple examples for the schema. Each example Can be any value e.g. literal, method reference or json!(...).
  • title = ... Literal string value. Can be used to define title for enum in OpenAPI document. Some OpenAPI code generation libraries also use this field as a name for the struct.
  • as = ... Can be used to define alternative path and name for the schema what will be used in the OpenAPI. E.g as = path::to::Pet. This would make the schema appear in the generated OpenAPI spec as path.to.Pet. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.

Create enum with numeric values.

#[derive(ToSchema)]
#[repr(u8)]
#[schema(default = default_value, example = 2)]
enum Mode {
    One = 1,
    Two,
 }

fn default_value() -> u8 {
    1
}

You can use skip and tag attributes from serde.

#[derive(ToSchema, serde::Serialize)]
#[repr(i8)]
#[serde(tag = "code")]
enum ExitCode {
    Error = -1,
    #[serde(skip)]
    Unknown = 0,
    Ok = 1,
 }

§Generic schemas

Utoipa supports full set of deeply nested generics as shown below. The type will implement ToSchema if and only if all the generic types implement ToSchema by default. That is in Rust impl<T> ToSchema for MyType<T> where T: Schema { ... }. You can also specify bound = ... on the item to override the default auto bounds.

The as = ... attribute is used to define the prefixed or alternative name for the component in question. This same name will be used throughout the OpenAPI generated with utoipa when the type is being referenced in OpenApi derive macro or in utoipa::path(...) macro.

 #[derive(ToSchema)]
 #[schema(as = path::MyType<T>)]
 struct Type<T> {
     t: T,
 }

 #[derive(ToSchema)]
 struct Person<'p, T: Sized, P> {
     id: usize,
     name: Option<Cow<'p, str>>,
     field: T,
     t: P,
 }

 #[derive(ToSchema)]
 #[schema(as = path::to::PageList)]
 struct Page<T> {
     total: usize,
     page: usize,
     pages: usize,
     items: Vec<T>,
 }

 #[derive(ToSchema)]
 #[schema(as = path::to::Element<T>)]
 enum E<T> {
     One(T),
     Many(Vec<T>),
 }

When generic types are registered to the OpenApi the full type declaration must be provided. See the full example in test schema_generics.rs

§Examples

Simple example of a Pet with descriptions and object level example.

/// This is a pet.
#[derive(ToSchema)]
#[schema(example = json!({"name": "bob the cat", "id": 0}))]
struct Pet {
    /// Unique id of a pet.
    id: u64,
    /// Name of a pet.
    name: String,
    /// Age of a pet if known.
    age: Option<i32>,
}

The schema attribute can also be placed at field level as follows.

#[derive(ToSchema)]
struct Pet {
    #[schema(example = 1, default = 0)]
    id: u64,
    name: String,
    age: Option<i32>,
}

You can also use method reference for attribute values.

#[derive(ToSchema)]
struct Pet {
    #[schema(example = u64::default, default = u64::default)]
    id: u64,
    #[schema(default = default_name)]
    name: String,
    age: Option<i32>,
}

fn default_name() -> String {
    "bob".to_string()
}

For enums and unnamed field structs you can define schema at type level.

#[derive(ToSchema)]
#[schema(example = "Bus")]
enum VehicleType {
    Rocket, Car, Bus, Submarine
}

Also you write mixed enum combining all above types.

#[derive(ToSchema)]
enum ErrorResponse {
    InvalidCredentials,
    #[schema(default = String::default, example = "Pet not found")]
    NotFound(String),
    System {
        #[schema(example = "Unknown system failure")]
        details: String,
    }
}

It is possible to specify the title of each variant to help generators create named structures.

#[derive(ToSchema)]
enum ErrorResponse {
    #[schema(title = "InvalidCredentials")]
    InvalidCredentials,
    #[schema(title = "NotFound")]
    NotFound(String),
}

Use xml attribute to manipulate xml output.

#[derive(ToSchema)]
#[schema(xml(name = "user", prefix = "u", namespace = "https://user.xml.schema.test"))]
struct User {
    #[schema(xml(attribute, prefix = "u"))]
    id: i64,
    #[schema(xml(name = "user_name", prefix = "u"))]
    username: String,
    #[schema(xml(wrapped(name = "linkList"), name = "link"))]
    links: Vec<String>,
    #[schema(xml(wrapped, name = "photo_url"))]
    photos_urls: Vec<String>
}

Use of Rust’s own #[deprecated] attribute will reflect to generated OpenAPI spec.

#[derive(ToSchema)]
#[deprecated]
struct User {
    id: i64,
    username: String,
    links: Vec<String>,
    #[deprecated]
    photos_urls: Vec<String>
}

Enforce type being used in OpenAPI spec to String with value_type and set format to octet stream with SchemaFormat::KnownFormat(KnownFormat::Binary).

#[derive(ToSchema)]
struct Post {
    id: i32,
    #[schema(value_type = String, format = Binary)]
    value: Vec<u8>,
}

Enforce type being used in OpenAPI spec to String with value_type option.

#[derive(ToSchema)]
#[schema(value_type = String)]
struct Value(i64);

Override the Bar reference with a custom::NewBar reference.

#[derive(ToSchema)]
struct Value {
    #[schema(value_type = custom::NewBar)]
    field: Bar,
};

Use a virtual Object type to render generic object (type: object) in OpenAPI spec.

#[derive(ToSchema)]
struct Value {
    #[schema(value_type = Object)]
    field: Bar,
};

More examples for value_type in IntoParams derive docs.

Serde rename / rename_all will take precedence over schema rename / rename_all.

#[derive(utoipa::ToSchema, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
#[schema(rename_all = "UPPERCASE")]
enum Random {
    #[serde(rename = "string_value")]
    #[schema(rename = "custom_value")]
    String(String),

    Number {
        id: i32,
    }
}

Add title to the enum.

#[derive(utoipa::ToSchema)]
#[schema(title = "UserType")]
enum UserType {
    Admin,
    Moderator,
    User,
}

Example with validation attributes.

#[derive(utoipa::ToSchema)]
struct Item {
    #[schema(maximum = 10, minimum = 5, multiple_of = 2.5)]
    id: i32,
    #[schema(max_length = 10, min_length = 5, pattern = "[a-z]*")]
    value: String,
    #[schema(max_items = 5, min_items = 1)]
    items: Vec<String>,
}

Use schema_with to manually implement schema for a field.

fn custom_type() -> Object {
    ObjectBuilder::new()
        .schema_type(utoipa::openapi::schema::Type::String)
        .format(Some(utoipa::openapi::SchemaFormat::Custom(
            "email".to_string(),
        )))
        .description(Some("this is the description"))
        .build()
}

#[derive(utoipa::ToSchema)]
struct Value {
    #[schema(schema_with = custom_type)]
    id: String,
}

Use as attribute to change the name and the path of the schema in the generated OpenAPI spec.

 #[derive(utoipa::ToSchema)]
 #[schema(as = api::models::person::Person)]
 struct Person {
     name: String,
 }

Use bound attribute to override the default impl bounds.

bound = ... accepts a string containing zero or more where-predicates separated by comma, as the similar syntax to serde(bound = ...). If bound = ... exists, the default auto bounds (requiring all generic types to implement ToSchema) will not be applied anymore, and only the specified predicates are added to the where clause of generated impl blocks.

// Override the default bounds to only require `T: ToSchema`, ignoring unused `U`.
#[derive(utoipa::ToSchema, serde::Serialize)]
#[schema(bound = "T: utoipa::ToSchema")]
struct Partial<T, U> {
    used_in_api: T,
    #[serde(skip)]
    not_in_api: std::marker::PhantomData<U>,
}

// Just remove the auto-bounds. So we got `Unused<T>: ToSchema` for any `T`.
#[derive(utoipa::ToSchema, serde::Serialize)]
#[schema(bound = "")]
struct Unused<T> {
    #[serde(skip)]
    _marker: std::marker::PhantomData<T>,
}

Use no_recursion attribute to break from looping schema tree e.g. Pet -> Owner -> Pet.

no_recursion attribute can be provided on named field of a struct, on unnamed struct or unnamed enum variant. It must be provided in case of looping schema tree in order to stop recursion. Failing to do so will cause runtime panic.

#[derive(ToSchema)]
pub struct Pet {
    name: String,
    owner: Owner,
}

#[derive(ToSchema)]
pub struct Owner {
    name: String,
    #[schema(no_recursion)]
    pets: Vec<Pet>,
}