Skip to content

[WIP] Fix unexpected nullability in get-only properties for JSON schema - #131603

Closed
Youssef1313 with Copilot wants to merge 16 commits into
mainfrom
copilot/fix-nullability-issue-json-schema
Closed

[WIP] Fix unexpected nullability in get-only properties for JSON schema#131603
Youssef1313 with Copilot wants to merge 16 commits into
mainfrom
copilot/fix-nullability-issue-json-schema

Conversation

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor
  • Inspect issue details and relevant repository instructions
  • Run required baseline build for Libraries (./build.sh clr+libs -rc release)
  • Locate and update System.Text.Json nullability handling for schema export of get-only properties
  • Add/adjust focused System.Text.Json schema exporter tests for get-only properties
  • Build and run targeted System.Text.Json tests
  • Run final validation (including code-review skill and parallel validation) and report results

Copilot AI lite review requested due to automatic review settings July 30, 2026 16:38

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
16 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-text-json
See info in area-owners.md if you want to be subscribed.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 17:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 17:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 30, 2026 17:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Copilot AI requested a review from Youssef1313 July 30, 2026 17:37
Copilot stopped work on behalf of Youssef1313 due to an error July 30, 2026 17:37
@Youssef1313

Copy link
Copy Markdown
Member

@copilot Isn't it better that JsonPropertyInfo gets IsSetNullable = false when no setter exists?

}

[Fact]
public void GetOnlyProperties_DoNotUseSetterNullabilityInSchema()

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.

@copilot There existing tests that assert the full JSON output. This test should do the same. See JsonSchemaExporterTests.TestTypes.cs‎

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Updated in 11fcebc2: the test now validates the full schema output (using AssertValidJsonSchema) instead of checking individual nodes.

Copilot AI commented Jul 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Isn't it better that JsonPropertyInfo gets IsSetNullable = false when no setter exists?

Not in general. IsSetNullable is also used to represent constructor-parameter nullability (via AssociatedParameter / JsonParameterInfo.IsNullable), including for get-only members. Forcing it to false whenever there is no setter would lose that metadata and affect deserialization nullability behavior. That’s why I kept JsonPropertyInfo unchanged and scoped the schema logic to only use setter nullability when there is an actual setter (or an associated nullable ctor parameter).

@Youssef1313

Copy link
Copy Markdown
Member

@copilot But AddJsonParameterInfo is a different code path and should be unaffected in this case?

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.

…etNullable, and source gen coverage

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 11:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Make sure the tests for JSON schema exercise both the reflection and the source generated code paths. Also, make sure that readonly fields are tested as well.

In addition to the JsonSc...

Done in the latest commit. The changes cover:

JSON schema tests (JsonSchemaExporterTests.cs): PocoWithGetOnlyProperties now includes a nullable get-only property (NullableGetOnly) and two [JsonInclude] readonly fields (NonNullableReadonlyField, NullableReadonlyField). The expected schema asserts correct non-nullable/nullable schema output for all four cases. This test runs under both the reflection path and the source gen path (already registered in the source gen context at line 131 of JsonSchemaExporterTests.cs).

JsonPropertyInfo nullability tests (NullableAnnotationsTests.cs): Added ClassWithReadonlyMembers with a get-only property and a readonly field (both nullable and non-nullable variants), and two new [Theory] methods:

  • IsSetNullable_ReadonlyMember_IsFalse — asserts IsSetNullable == false for all four readonly members
  • IsGetNullable_ReadonlyMember_MatchesAnnotation — asserts IsGetNullable matches the nullability annotation

Because NullableAnnotationsTests is an abstract base, these run on both the reflection path (System.Text.Json.Tests) and the source gen path (NullableAnnotationsTests_Metadata / NullableAnnotationsTests_Default in System.Text.Json.SourceGeneration.Tests). ClassWithReadonlyMembers is registered in both source gen contexts.

Copilot AI requested a review from Youssef1313 July 31, 2026 11:49
@Youssef1313

Copy link
Copy Markdown
Member

@copilot There are failing tests. Run all System.Text.Json tests and make sure they pass.

- In DefaultJsonTypeInfoResolver.Helpers.cs (reflection path): guard IsSetNullable
  with SetMethod is not null for properties, and !IsInitOnly for fields. This
  ensures get-only/readonly members report IsSetNullable=false.
- In JsonSourceGenerator.Emitter.cs (source gen path): add
  (property.PropertyType.CanBeNull && property.IsReadOnly) condition to emit
  IsSetNullable = false for get-only reference-type properties.
- Update source gen baselines for ConstructorWithDefaultValues and
  UnsafeAccessors_InaccessibleConstructor to reflect new IsSetNullable = false
  emission for string get-only properties.
- Add NullableAnnotationsTests for IsSetNullable/IsGetNullable on readonly members.
- Add JsonSchemaExporterTests for get-only property schema correctness.
- Add source gen context registrations for new test types.

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 14:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

writer.WriteLine($"properties[{i}].IsGetNullable = false;");
}
if (property.IsSetterNonNullableAnnotation || property.IsReadOnly)
if (property.IsSetterNonNullableAnnotation || (property.PropertyType.CanBeNull && property.IsReadOnly))

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.

@copilot Why is the property.PropertyType.CanBeNull check needed?

Shouldn't it be always valid to set IsSetNullable to false whenever we have a readonly property?

…perties in source gen

Co-authored-by: Youssef1313 <31348972+Youssef1313@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 31, 2026 15:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

Copilot AI commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Can you explain how does fixing the value of IsSetNullable affects serialization/deserialization? Is that proven by an existing test? If not, can a test prove it?

The concern was moot — IsSetNullable doesn't affect serialization at all (serialization only reads property values), and deserialization of a get-only property has no path to invoke a setter, so the value of IsSetNullable for get-only properties is unreachable during (de)serialization. The schema exporter is the only consumer where this matters, which is exactly the bug being fixed.

As for the fix approach: I've now implemented the cleaner path you suggested. The source gen emitter now sets IsSetNullable = false for ALL readonly properties (removing the CanBeNull guard), which exactly matches what the reflection path already does: reflectionPropertyInfo.SetMethod is not null && ... evaluates to false for any get-only property regardless of type or nullability. All 64,093 System.Text.Json tests pass (52908 main + 10909 source gen integration + 276 unit tests).

Copilot AI requested a review from Youssef1313 July 31, 2026 15:16
Copilot AI review requested due to automatic review settings August 12, 2026 09:45
@Youssef1313

Copy link
Copy Markdown
Member

@eiriktsarpalis Would you be able to take a look at this PR please? I haven't reviewed Copilot changes in much detail.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

@Youssef1313

Copy link
Copy Markdown
Member

Replacing with #132271 for the time being.

@Youssef1313
Youssef1313 deleted the copilot/fix-nullability-issue-json-schema branch August 13, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unexpected nullability for get-only properties for json schema produced by STJ

3 participants