Skip to content

fix: honour OAS required and nullable flags (#3911)#7585

Open
OMMHOA wants to merge 7 commits intomicrosoft:mainfrom
OMMHOA:issue-3911-fix
Open

fix: honour OAS required and nullable flags (#3911)#7585
OMMHOA wants to merge 7 commits intomicrosoft:mainfrom
OMMHOA:issue-3911-fix

Conversation

@OMMHOA
Copy link
Copy Markdown

@OMMHOA OMMHOA commented Apr 9, 2026

Implemented with heavy use of AI, manually reviewed the change. AI summary of the change:

Issue #3911 — Implementation Summary

Fixes Kiota generating all model properties as nullable regardless of the OAS required array and nullable flag.

Rule implemented: a property is marked non-nullable only when it is both listed in the parent schema's required array and its own schema does not carry nullable: true. All other combinations remain nullable (the safe default).


Files changed

src/Kiota.Builder/CodeDOM/CodeProperty.cs (previous session)

  • Added bool IsRequired { get; set; } property.
  • Updated Clone() to copy the field.

src/Kiota.Builder/Extensions/OpenApiSchemaExtensions.cs

  • Added internal static bool IsExplicitlyNullable(this IOpenApiSchema? schema) helper that detects OAS 3.0 nullable: true and OAS 3.1 type: null / anyOf [{type: null}] patterns.

src/Kiota.Builder/KiotaBuilder.cs

  • CreatePropertiesForModelClass — reads schema.Required and passes isRequired to each CreateProperty call.
  • CreateProperty — added bool isRequired = false parameter; sets prop.IsRequired = isRequired on every property; sets prop.Type.IsNullable = false when the property is required and IsExplicitlyNullable() returns false. Clones existingType before mutation to avoid corrupting shared type references.

src/Kiota.Builder/Refiners/CSharpRefiner.cs

  • MakeEnumPropertiesNullable — added .Where(x => !x.IsRequired) guard so required enum properties are no longer forced nullable.

src/Kiota.Builder/Writers/CSharp/CodePropertyWriter.cs

  • isNullableReferenceType check — added && codeElement.Type.IsNullable so the #nullable enable / ? block is only emitted when the type is actually nullable. Required non-nullable properties are written as plain public T Name { get; set; }.

Tests added

tests/Kiota.Builder.Tests/KiotaBuilderTests.cs

7 new tests in #region Issue-3911 verifying IsNullable and IsRequired on the Code DOM for:

Schema type required nullable Expected IsNullable Expected IsRequired
string false true
string true true
string true false
string true false
integer false true
object $ref false true
enum $ref false true
array false true

tests/Kiota.Builder.Tests/Writers/CSharp/CodePropertyWriterTests.cs

  • Required non-nullable reference type → no #nullable enable, no ? suffix.
  • Nullable reference type → has #nullable enable and ? suffix.
  • Required non-nullable enum → no #nullable enable, no ? suffix.

tests/Kiota.Builder.Tests/Writers/Java/CodePropertyWriterTests.cs

  • Required non-nullable → @jakarta.annotation.Nonnull, no @Nullable.

tests/Kiota.Builder.Tests/Writers/Php/CodePropertyWriterTests.cs

  • Required non-nullable → no ? type prefix, no = null default.

tests/Kiota.Builder.Tests/Writers/Python/CodePropertyWriterTests.cs

  • Required non-nullable → no Optional[...], no = None default.

Languages requiring no code changes

Java, PHP, and Python writers already consumed IsNullable faithfully and produce correct output as soon as the builder sets the flag correctly. Go, TypeScript, and Ruby were unaffected by design.

@OMMHOA OMMHOA requested a review from a team as a code owner April 9, 2026 19:51
@OMMHOA
Copy link
Copy Markdown
Author

OMMHOA commented Apr 9, 2026

@microsoft-github-policy-service agree

@OMMHOA OMMHOA marked this pull request as draft April 9, 2026 20:03
@OMMHOA OMMHOA marked this pull request as ready for review April 10, 2026 09:40
@WolfgangHG
Copy link
Copy Markdown
Contributor

Just saw this issue, and a alarm bell rings ;-): some time ago, I run into a "required" problem with a NSwag generated client: I had to build an api client and the openapi spec was not not correct and did not define fields as optional.
The reason was probably that it was converted from Swagger 2 to OpenApi 3 and the required/optional definitions were not checked.

After re-generating the client, it failed to parse e.g. server responses because fields missing in the response were considered be required.

This might be a sample class (not exactly the property that caused the problem originally):

    SampleModel:
      type: object
      properties:
        field:
          type: number

With the switch described below, NSwag generates this (working) nullable property:

[Newtonsoft.Json.JsonProperty("field", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public double? Field { get; set; }

With default settings, it would create a non-nullable property:

[Newtonsoft.Json.JsonProperty("field", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public double Field { get; set; }

Could this happen here? If yes: could you add a switch to use the old way?

NSwag fortunately had a switch for this - https://www.github.com/RicoSuter/NSwag/issues/2313#issuecomment-516471348

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.

2 participants