Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToSchema derives array with items with allOf combination of the types of all the tuple elements #901

Closed
taladar opened this issue May 3, 2024 · 11 comments · Fixed by #1103
Labels
enhancement New feature or request investigate Futher investigation needed before other action

Comments

@taladar
Copy link

taladar commented May 3, 2024

Given e.g.

use utoipa::{OpenApi, ToSchema};

#[derive(ToSchema)]
struct A((Option<String>, String));

#[derive(OpenApi)]
#[openapi(components(schemas(A)))]
struct Api;

fn main() {
    println!("{}", Api::openapi().to_pretty_json().unwrap())
}

we get

{
  "openapi": "3.0.3",
  "info": {
    "title": "utoipa-test",
    "description": "",
    "license": {
      "name": ""
    },
    "version": "0.1.0"
  },
  "paths": {},
  "components": {
    "schemas": {
      "A": {
        "type": "array",
        "items": {
          "allOf": [
            {
              "type": "string",
              "nullable": true
            },
            {
              "type": "string"
            }
          ]
        }
      }
    }
  }
}

which seems to be the schema for a type that fulfills all the requirements at the same time instead of one where each element fulfills one of the requirements.

This happens for both enum and struct fields and it does not seem to matter if the field is named which leads me to conclude that the location of the tuple within the type we derive ToSchema on probably doesn't matter.

@taladar
Copy link
Author

taladar commented May 3, 2024

Tuples don't seem to be supported exactly in OpenAPI but it would probably be possible to at least use anyOf and minItems and maxItems to get as close as OpenAPI allows the validation to go.

Alternatively if someone uses a tuple and it is not supported by utoipa at all it should probably lead to a compile error.

@emersion
Copy link

It should be possible to set minItems/maxItems to constrain the size of the array, then use prefixItems to describe each entry.

@juhaku
Copy link
Owner

juhaku commented Sep 18, 2024

According to how serde serializes tuples https://serde.rs/json.html see the struct X it will serialize to array of 2 fields. Thus the generated schema is also generated accordingly.

@taladar
Copy link
Author

taladar commented Sep 18, 2024

But this schema requires every element of the tuple to satisfy the types of all of them which obviously won't work.

@juhaku
Copy link
Owner

juhaku commented Sep 18, 2024

@taladar Ah, true, instead it should serialize as anyOf. I'll try to check this out and fix it soon.

@juhaku juhaku added the bug Something isn't working label Sep 18, 2024
@emersion
Copy link

anyOf wouldn't faithfully represent the tuple constraints. My suggestion above would.

@juhaku
Copy link
Owner

juhaku commented Sep 18, 2024

True, the limitation should already be present on some tuples though. It should actually set that the array should contain 2 items. But it does not set prefix items though. But it might be that it does not take account all cases. Nonetheless while those min_items and max_items are provided they are only for visual validation and does not really prevent users of providing more or less items if the endpoint was executed e.g. with curl.

.to_array_builder()
.max_items(Some(#fields_len))
.min_items(Some(#fields_len))
#description

@juhaku juhaku added investigate Futher investigation needed before other action and removed bug Something isn't working labels Sep 18, 2024
@taladar
Copy link
Author

taladar commented Sep 18, 2024

Technically speaking the entire schema does not prevent any client from sending any random data to the endpoint.

@juhaku
Copy link
Owner

juhaku commented Sep 18, 2024

Yeah, it just shows "what a good guy should send"

@juhaku
Copy link
Owner

juhaku commented Oct 7, 2024

@emersion That is true,

I'll change the tuple implementation out of the allOf thingly. That was a relic from past in the OpenAPI 3.0 which did not conform fully to JSON Schema spec. Since OpenAPI 3.1 it is fully conforming the JSON Schema we can use the prefixItems defined here: https://json-schema.org/understanding-json-schema/reference/array#tupleValidation. This allows full tuple support for OpenAPI as well as stated by @emersion.

@juhaku juhaku added the enhancement New feature or request label Oct 7, 2024
@juhaku juhaku moved this to In Progress in utoipa kanban Oct 7, 2024
juhaku added a commit that referenced this issue Oct 7, 2024
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
juhaku added a commit that referenced this issue Oct 7, 2024
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
juhaku added a commit that referenced this issue Oct 7, 2024
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
juhaku added a commit that referenced this issue Oct 7, 2024
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
juhaku added a commit that referenced this issue Oct 7, 2024
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
@juhaku juhaku closed this as completed in 8bbc5d9 Oct 7, 2024
@github-project-automation github-project-automation bot moved this from In Progress to Done in utoipa kanban Oct 7, 2024
@emersion
Copy link

emersion commented Oct 7, 2024

Thank you so much!

@juhaku juhaku moved this from Done to Released in utoipa kanban Oct 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request investigate Futher investigation needed before other action
Projects
Status: Released
Development

Successfully merging a pull request may close this issue.

3 participants