Derive Macro utoipa::Component

source · []
#[derive(Component)]
{
    // Attributes available to this derive:
    #[component]
}
Expand description

Component dervice macro

This is #[derive] implementation for Component trait. The macro accepts one component attribute optionally which can be used to enhance generated documentation. The attribute can be placed at item level or field level in struct and enums. Currently placing this attribute to unnamed field does not have any effect.

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

#[deprecated] attribute supports adding addtional 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.

Struct Optional Configuration Options

  • example = ... Can be either json!(...) or literal string that can be parsed to json. json! should be something that serde_json::json! can parse as a serde_json::Value. 1
  • xml(...) Can be used to define Xml object properties applicable to Structs.

Enum Optional Configuration Options

  • example = ... Can be literal value, method reference or json!(...). 2
  • default = ... Can be literal value, method reference or json!(...). 2

Unnamed Field Struct Optional Configuration Options

  • example = ... Can be literal value, method reference or json!(...). 2
  • default = ... Can be literal value, method reference or json!(...). 2
  • format = ... ComponentFormat to use for the property. 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 the where default type does not correspond to the actual type e.g. when any thrid-party types are used which are not components nor primitive types. With value_type we can enforce type used to certain type. Value type may only be primitive type or String. Generic types are not allowed.

Named Fields Optional Configuration Options

  • example = ... Can be literal value, method reference or json!(...). 2
  • default = ... Can be literal value, method reference or json!(...). 2
  • format = ... ComponentFormat to use for the property. 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.
  • value_type = ... Can be used to override default type derived from type of the field used in OpenAPI spec. This is useful in cases the where default type does not correspond to the actual type e.g. when any thrid-party types are used which are not components nor primitive types. With value_type we can enforce type used to certain type. Value type may only be primitive type or String. Generic types are not allowed.

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.

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

Component 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 in container level.
  • rename = "..." Supported only in field or variant level.
  • skip = "..." Supported only in field or variant level.

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

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

#[derive(Serialize, Component)]
#[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,
}

Examples

Example struct with struct level example.

#[derive(Component)]
#[component(example = json!({"name": "bob the cat", "id": 0}))]
struct Pet {
    id: u64,
    name: String,
    age: Option<i32>,
}

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

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

You can also use method reference for attribute values.

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

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

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

#[derive(Component)]
#[component(example = "Bus")]
enum VechileType {
    Rocket, Car, Bus, Submarine
}

Also you write complex enum combining all above types.

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

Use xml attribute to manipulate xml output.

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

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

#[derive(Component)]
#[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 octect stream with ComponentFormat::Binary.

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

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

#[derive(Component)]
#[component(value_type = String)]
struct Value(i64);

  1. json feature need to be enabled for json!(...) type to work. 

  2. Values are converted to string if json feature is not enabled.