Skip to content

Commit

Permalink
Adds support for prefixItems on Array (#1103)
Browse files Browse the repository at this point in the history
This PR adds support for `prefixItems` as defined in JSON schema
specification https://json-schema.org/understanding-json-schema/reference/array#tupleValidation.
The `prefixItems` are used to correctly represent tuple values Rust
tuples. This will remove the old `allOf` behavior known from OpenAPI 3.0
which fails to correctly represent a tuple. Prefix items are conforming
OpenAPI 3.1 and is coming from JSON Schema.

Add new type `ArrayItems` what represent [`Array::items`] supported
values.

 ### Breaking

 This commit removes `allOf` tuple behavior, replacing with with all new
 `prefixItems` while setting `items` to false.

Closes #901
  • Loading branch information
juhaku authored Oct 7, 2024
1 parent 80ff67e commit 8bbc5d9
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 48 deletions.
1 change: 1 addition & 0 deletions utoipa-gen/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

### Breaking

* Adds support for `prefixItems` on `Array` (https://github.com/juhaku/utoipa/pull/1103)
* Auto collect tuple responses schema references (https://github.com/juhaku/utoipa/pull/1071)
* Implement automatic schema collection for requests (https://github.com/juhaku/utoipa/pull/1066)
* Refactor enums processing (https://github.com/juhaku/utoipa/pull/1059)
Expand Down
22 changes: 10 additions & 12 deletions utoipa-gen/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1199,35 +1199,32 @@ impl ComponentSchema {
.children
.as_ref()
.map_try(|children| {
let all_of = children
let prefix_items = children
.iter()
.map(|child| {
let features = if child.is_option() {
let mut features = if child.is_option() {
vec![Feature::Nullable(Nullable::new())]
} else {
Vec::new()
};
// Prefix item is always inlined
features.push(Feature::Inline(true.into()));

match ComponentSchema::new(ComponentSchemaProps {
container,
type_tree: child,
features,
description: None,
}) {
Ok(child) => Ok(child.to_token_stream()),
Ok(child) => Ok(quote! {
Into::<utoipa::openapi::schema::Schema>::into(#child)
}),
Err(diagnostics) => Err(diagnostics),
}
})
.collect::<Result<Vec<_>, Diagnostics>>()?
.into_iter()
.fold(
quote! { utoipa::openapi::schema::AllOfBuilder::new() },
|mut all_of, child_tokens| {
all_of.extend(quote!( .item(#child_tokens) ));

all_of
},
);
.collect::<Array<_>>();

let nullable_schema_type = ComponentSchema::get_schema_type_override(
nullable_feat,
Expand All @@ -1236,7 +1233,8 @@ impl ComponentSchema {
Result::<TokenStream, Diagnostics>::Ok(quote! {
utoipa::openapi::schema::ArrayBuilder::new()
#nullable_schema_type
.items(#all_of)
.items(utoipa::openapi::schema::ArrayItems::False)
.prefix_items(#prefix_items.to_vec())
#description_stream
#deprecated
})
Expand Down
59 changes: 32 additions & 27 deletions utoipa-gen/tests/schema_derive_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4920,28 +4920,34 @@ fn derive_tuple_named_struct_field() {
info: (String, i64, bool, Person)
}
};

assert_json_eq!(
value,
json!({
"properties": {
"info": {
"items": {
"allOf": [
{
"type": "string"
},
{
"type": "integer",
"format": "int64",
},
{
"type": "boolean",
"prefixItems": [
{
"type": "string"
},
{
"type": "integer",
"format": "int64",
},
{
"type": "boolean",
},
{
"properties": {
"name": {
"type": "string"
}
},
{
"$ref": "#/components/schemas/Person"
}
]
},
"required": ["name"],
"type": "object"
}
],
"items": false,
"type": "array"
}
},
Expand All @@ -4966,17 +4972,16 @@ fn derive_nullable_tuple() {
json!({
"properties": {
"info": {
"items": {
"allOf": [
{
"type": "string"
},
{
"type": "integer",
"format": "int64",
},
]
},
"prefixItems": [
{
"type": "string"
},
{
"type": "integer",
"format": "int64",
},
],
"items": false,
"type": ["array", "null"],
"deprecated": true,
"description": "This is description",
Expand Down
1 change: 1 addition & 0 deletions utoipa/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ to look into changes introduced to **`utoipa-gen`**.

### Breaking

* Adds support for `prefixItems` on `Array` (https://github.com/juhaku/utoipa/pull/1103)
* Implement automatic schema collection for requests (https://github.com/juhaku/utoipa/pull/1066)
* Refactor enums processing (https://github.com/juhaku/utoipa/pull/1059)
* Feature openapi 31 (https://github.com/juhaku/utoipa/pull/981)
Expand Down
Loading

0 comments on commit 8bbc5d9

Please sign in to comment.