Skip to content

Do not ignore multiple types when serializing to 3.0#2960

Open
Youssef1313 wants to merge 1 commit into
microsoft:mainfrom
Youssef1313:dev/ygerges/multiple-types-3
Open

Do not ignore multiple types when serializing to 3.0#2960
Youssef1313 wants to merge 1 commit into
microsoft:mainfrom
Youssef1313:dev/ygerges/multiple-types-3

Conversation

@Youssef1313

@Youssef1313 Youssef1313 commented Jul 15, 2026

Copy link
Copy Markdown
Member

Fixes #2939

  • The change to ToSingleIdentifier is only a simplification to make it easier to read.
  • Type serialization is now split to two path to be easier to read, especially that 3.0 needs more parameters/info than 2.0.
  • The behavior of 2.0 is maintained as-is, no change there
  • Previously, in 3.0, we ignored when Type had multiple values (e.g, String and Integer). This is now handled using oneOf or anyOf (whichever isn't used by the current schema already). If both are used, we ignore as it we used to in the past.
  • The general idea here is:
    1. We take the Type.
    2. We remove Null from it (if it exists).
    3. If, after removing null, we have a single type, we simply emit it, and conditionally emit nullable: true depending on whether null was existing. This is the same as the existing behavior.
    4. If, after removing null, we have more than one type, we create a oneOf/anyOf with children schemas handling each type individually.
  • The reason around all that is that because type only supports a single value when using OpenApi 3.0.

For context: https://spec.openapis.org/oas/v3.0.4.html#json-schema-keywords

The following keywords are taken from the JSON Schema definition but their definitions were adjusted to the OpenAPI Specification.
type - Value MUST be a string. Multiple types via an array are not supported.

Comment on lines +1974 to +1977
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer,
};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, this was resulting in an empty schema, which will match anything.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer | JsonSchemaType.Null,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, the type was ignored, and only anyOf was emitted.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, the type was ignored and only anyOf was emitted.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer | JsonSchemaType.Null,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, the type was ignored and only oneOf was emitted.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, only oneOf was emitted.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer | JsonSchemaType.Null,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my change, an empty schema was generated, allowing anything to match.

@Youssef1313 Youssef1313 force-pushed the dev/ygerges/multiple-types-3 branch from 165e0eb to a663f6f Compare July 15, 2026 11:31
{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this test, the behavior is the same as in the past. We are not respecting Type, and I can't see an easy way to respect it.

It's technically possible to emit "allOf" that contains a schema representing the types as "oneOf" or "anyOf" schema, and then another schema that wraps the existing anyOf/oneOf. But that's a major re-write I didn't want to introduce.

{
var schema = new OpenApiSchema()
{
Type = JsonSchemaType.String | JsonSchemaType.Integer | JsonSchemaType.Null,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. This wasn't (and is still not) respected. We could respect it but it will be a more bigger re-write.

@Youssef1313 Youssef1313 marked this pull request as ready for review July 15, 2026 11:36
@Youssef1313 Youssef1313 requested a review from a team as a code owner July 15, 2026 11:36

@baywet baywet left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this kind of normalization should not be done during serialization, but rather through a walker which would be called before serialization.

See #808 and other related issues.

Case in point, we've had to revert some of the normalization done for null/nullable (to oneOf) in #2933

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider representing multiple types in 3.0 using anyOf or oneOf

2 participants