Skip to content

Commit

Permalink
Fix bug in generic schemas on OpenApi derive macro
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 committed Jan 5, 2025
1 parent 9482728 commit 7ac1f68
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 7ac1f68

Please sign in to comment.