Skip to content

fix(reader): preserve Null flag when nullable appears before type in V3.0/V3.1/V3.2 deserializers#2853

Merged
baywet merged 3 commits into
mainfrom
copilot/fix-openapi-deserializer-nullable-issue
May 26, 2026
Merged

fix(reader): preserve Null flag when nullable appears before type in V3.0/V3.1/V3.2 deserializers#2853
baywet merged 3 commits into
mainfrom
copilot/fix-openapi-deserializer-nullable-issue

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 26, 2026

The V3.1/V3.2 schema deserializer's "type" handler unconditionally overwrote o.Type, discarding any JsonSchemaType.Null flag already set by a preceding "nullable": true handler. Result: nullable: true was silently dropped whenever it appeared before type in the document.

Description

Key-order bug in OpenApiV31Deserializer (and V32): the "nullable" handler sets o.Type = JsonSchemaType.Null when type is unknown, but the "type" handler then does a direct assignment, erasing it. V3.0 is unaffected by the production code bug — it applies nullable as a post-processing step after all keys are parsed, making it inherently order-independent.

Before:

"type", (o, n, doc) =>
{
    if (n is ValueNode)
        o.Type = n.GetScalarValue()?.ToJsonSchemaType(); // overwrites Null flag
    ...
}

After:

"type", (o, n, doc) =>
{
    var preserveNull = o.Type.HasValue && o.Type.Value.HasFlag(JsonSchemaType.Null);
    if (n is ValueNode)
    {
        var parsedType = n.GetScalarValue()?.ToJsonSchemaType();
        o.Type = preserveNull ? parsedType | JsonSchemaType.Null : parsedType;
    }
    ...
}

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

Changes Made

  • V31/OpenApiSchemaDeserializer.cs: "type" handler now checks for an existing Null flag (set by a preceding nullable: true) and preserves it via bitwise OR for both scalar and array type values
  • V32/OpenApiSchemaDeserializer.cs: same fix applied
  • V31Tests/OpenApiSchemaTests.cs: added parameterized test asserting nullable before or after type both yield JsonSchemaType.String | JsonSchemaType.Null
  • V3Tests/OpenApiSchemaTests.cs: same test duplicated for OpenAPI 3.0
  • V32Tests/OpenApiSchemaTests.cs: same test duplicated for OpenAPI 3.2

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • All existing tests pass

Checklist

  • My code follows the code style of this project
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Versions applicability

  • My change applies to the version 1.X of the library, if so PR link:
  • My change applies to the version 2.X of the library, if so PR link:
  • My change applies to the version 3.X of the library, if so PR link:
  • I have evaluated the applicability of my change against the other versions above.

Additional Notes

The V3.0 deserializer is not affected by the production code bug — it applies nullable as a deferred post-processing step after all keys have been parsed, making it inherently order-independent. Tests for V3.0 were added to confirm this behaviour is and remains correct.

…able in V3.1/V3.2 deserializers

Agent-Logs-Url: https://github.com/microsoft/OpenAPI.NET/sessions/40596ef1-e9f2-4d1b-b9e2-0650b96d73b4

Co-authored-by: baywet <7905502+baywet@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix OpenAPI 3.1 V31 deserializer losing nullable for key order fix(reader): preserve Null flag when nullable appears before type in V3.1/V3.2 deserializers May 26, 2026
Copilot AI requested a review from baywet May 26, 2026 10:16
Copilot finished work on behalf of baywet May 26, 2026 10:16
@baywet
Copy link
Copy Markdown
Member

baywet commented May 26, 2026

@copilot duplicate the test for 3.0 and 3.2 as well

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 26, 2026

@copilot duplicate the test for 3.0 and 3.2 as well

Done in de72b1d — added the same ParseSchemaWithNullableBeforeOrAfterTypePreservesNullFlag theory test to V3Tests/OpenApiSchemaTests.cs (3.0) and V32Tests/OpenApiSchemaTests.cs (3.2), covering both key orderings in each version.

Copilot AI changed the title fix(reader): preserve Null flag when nullable appears before type in V3.1/V3.2 deserializers fix(reader): preserve Null flag when nullable appears before type in V3.0/V3.1/V3.2 deserializers May 26, 2026
Copilot finished work on behalf of baywet May 26, 2026 12:39
@baywet baywet marked this pull request as ready for review May 26, 2026 12:48
@baywet baywet requested a review from a team as a code owner May 26, 2026 12:48
@baywet
Copy link
Copy Markdown
Member

baywet commented May 26, 2026

do not merge before #2854 has been merged and published.

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
21.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@baywet baywet enabled auto-merge May 26, 2026 15:59
@baywet baywet merged commit 2b9d7f4 into main May 26, 2026
23 of 27 checks passed
@baywet baywet deleted the copilot/fix-openapi-deserializer-nullable-issue branch May 26, 2026 16:16
@baywet baywet mentioned this pull request May 26, 2026
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.

OpenAPI 3.1 V31 deserializer loses nullable when "nullable" key appears before "type" (key-order sensitive)

3 participants