Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for real generics (#1034)
This PR adds support for real generics which allows users to use deeply nested generic types as schemas without the alias hassle known to users. This commit will remove the old aliases support and implement completely new generics handling. (Something that many has been longing for long) This commit further enhances the implementation for full generic support. From now on the full type paths need used to declare the types in the `OpenApi` and `#[utoipa::path]` macros. As further elaborated here #1020 (comment) the name of the schema is now resolved form the type name and possible generic arguments or via `as = ...` attribute and possible generic arguments. This name is then used across the OpenApi. This makes it a single place to define the name or prefixed name for the type unlike previously the path of the schema in `OpenApi` macro or `request_body` or `response body` was added to the name. This PR will also change the `schema!(...)` macro functionality to correctly generate schemas for arbitrary types even generic ones. Prior to this commit the generics where not resolved correctly. Still all generic arguments must implement `ToSchema` trait in order to generate schema in first place. Clean up the code and enhance documentation. ## Breaking changes - Removed old aliases support - Schemas now need to be defined with full type path as shown below in example with all generic if any - If defined `schema(as = ...)` attribute now defines the prefix for the name of the component throughout OpenAPI references thus path that is possibly defined to `request_body` or responses `body` **will not affect** the name of the schema anymore. Example of new syntax. ```rust #[derive(ToSchema)] #[schema(as = path::MyType<T>)] struct Type<T: ToSchema> { t: T, } #[derive(ToSchema)] struct Person<'p, T: Sized + ToSchema, P: ToSchema> { id: usize, name: Option<Cow<'p, str>>, field: T, t: P, } #[derive(ToSchema)] #[schema(as = path::to::PageList)] struct Page<T: ToSchema> { total: usize, page: usize, pages: usize, items: Vec<T>, } #[derive(ToSchema)] #[schema(as = path::to::Element<T>)] enum E<T: ToSchema> { One(T), Many(Vec<T>), } #[utoipa::path( get, path = "/handler", request_body = inline(Person<'_, String, Type<i32>>), responses( (status = OK, body = inline(Page<Person<'_, String, Type<i32>>>)), (status = 400, body = Page<Person<'_, String, Type<i32>>>) ) )] async fn handler() {} #[derive(OpenApi)] #[openapi( components( schemas( Person::<'_, String, Type<i32>>, Page::<Person<'_, String, Type<i32>>>, E::<String>, ) ), paths( handler ) )] struct ApiDoc; ```
- Loading branch information