Skip to content

Commit

Permalink
Fix bug in generic schemas on OpenApi derive macro (#1277)
Browse files Browse the repository at this point in the history
This commit fixes bug caused by changes introduced here #1184 by adding
necessary changes to how schema is added to an OpenApi when it is added
via `components(schemas(...))` attribute of the OpenApi derive macro.

Fixes #1265
  • Loading branch information
juhaku authored Jan 5, 2025
1 parent 9482728 commit ee1067e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
4 changes: 4 additions & 0 deletions utoipa-gen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Fixed

* Fix bug in generic schemas on OpenApi derive macro (https://github.com/juhaku/utoipa/pull/1277)

### Changed

* Update axum to v0.8 (https://github.com/juhaku/utoipa/pull/1269)
Expand Down
7 changes: 5 additions & 2 deletions utoipa-gen/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ impl Parse for Components {
}
}

impl crate::ToTokensDiagnostics for Components {
impl ToTokensDiagnostics for Components {
fn to_tokens(&self, tokens: &mut TokenStream) -> Result<(), Diagnostics> {
if self.schemas.is_empty() && self.responses.is_empty() {
return Ok(());
Expand All @@ -659,7 +659,10 @@ impl crate::ToTokensDiagnostics for Components {
<#type_path as utoipa::ToSchema>::schemas(&mut schemas);
schemas
} )});
components.extend(quote! { .schema(#name, #schema) });
components.extend(quote! { .schema(#name, {
let mut generics = Vec::<utoipa::openapi::RefOr<utoipa::openapi::schema::Schema>>::new();
#schema
}) });

components
},
Expand Down
48 changes: 48 additions & 0 deletions utoipa-gen/tests/openapi_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,3 +525,51 @@ fn openapi_resolvle_recursive_references() {

assert_json_snapshot!(schemas);
}

#[test]
fn derive_generic_openapi_component_schemas() {
#[derive(Serialize, ToSchema)]
#[schema(as = dto::page::Response)]
#[serde(rename_all = "camelCase")]
pub struct Response<T: Serialize> {
pub list: Vec<T>,
pub num: u64,
pub size: u64,
pub total: u64,
}

pub mod unit {
use serde::Serialize;
use utoipa::ToSchema;

#[derive(Serialize, ToSchema)]
#[schema(as = dto::get::unit::Response)]
#[serde(rename_all = "camelCase")]
pub struct Response {
pub id: i64,
pub latitude: f64,
pub longitude: f64,
pub title: String,
pub description: Option<String>,
pub country: String,
pub region: Option<String>,
pub city: String,
pub address: String,
}
}

#[derive(OpenApi)]
#[openapi(
components(
schemas(
Response<unit::Response>,
)
)
)]
struct ApiDoc;

let doc = serde_json::to_value(ApiDoc::openapi()).expect("OpenApi is JSON serializable");
let schemas = doc.pointer("/components");

assert_json_snapshot!(schemas)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
source: utoipa-gen/tests/openapi_derive.rs
expression: schemas
snapshot_kind: text
---
{
"schemas": {
"dto.page.Response_dto.get.unit.Response": {
"properties": {
"list": {
"items": {
"$ref": "#/components/schemas/dto.get.unit.Response"
},
"type": "array"
},
"num": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"size": {
"format": "int64",
"minimum": 0,
"type": "integer"
},
"total": {
"format": "int64",
"minimum": 0,
"type": "integer"
}
},
"required": [
"list",
"num",
"size",
"total"
],
"type": "object"
}
}
}

0 comments on commit ee1067e

Please sign in to comment.