Skip to content

[http-client-csharp] Initialize omitted required collections during deserialization - #12090

Open
Jorge Rangel (jorgerangel-msft) with Copilot wants to merge 11 commits into
mainfrom
copilot/http-client-csharp-fix-json-round-trip
Open

Jorge Rangel (jorgerangel-msft) with Copilot wants to merge 11 commits into
mainfrom
copilot/http-client-csharp-fix-json-round-trip

Conversation

Copilot AI commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Deserialization accepts JSON that omits required, non-nullable collections but leaves them null. Accessing those collections or immediately serializing the returned model can then throw NullReferenceException.

  • Initialization: Extend empty-collection fallbacks to required non-nullable lists and dictionaries, including read-only collections.
    requiredCollection ?? new ChangeTrackingList<StringFixedEnum>()
  • Compatibility: Use assignable fallbacks for concrete List<T> customizations. Preserve optional and required-nullable handling, populated/empty collections, and explicit-null rejection.
  • Regression coverage: Add collection access/mutation, immediate J/W serialization without prior getter access, and concrete-list customization cases. Update affected generated output and baselines.

@azure-pipelines

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

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@microsoft-github-policy-service microsoft-github-policy-service Bot added the emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp label Sep 30, 2026
@pkg-pr-new

pkg-pr-new Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@typespec/http-client-csharp@12090

commit: 532e7bf

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 review overview

🔵 Needs a closer look

The required Cop static-analysis validation remains incomplete.

Review effort: Balanced
Findings: None

What changed in this PR

Fixes C# model deserialization so omitted required, non-nullable collections initialize empty and remain serializable.

Changes:

  • Adds collection fallbacks when invoking serialization constructors.
  • Regenerates affected JSON/XML model output.
  • Adds regression coverage for mutation, round-tripping, and explicit null rejection.
File Description
MrwSerializationTypeDefinition.cs Adds required non-nullable collection fallback.
RoundTripModelTests.cs Adds runtime regression tests.
DeserializeArrayProperties.cs Updates array baseline.
DeserializeDictionaryProperties.cs Updates dictionary baseline.
XmlDeserializationMethodHandlesUnwrappedListProperty.cs Updates unwrapped XML baseline.
XmlDeserializationMethodHandlesWrappedListProperty.cs Updates wrapped XML baseline.
DynamicModel.Serialization.cs Regenerates collection fallbacks.
ListWithContinuationTokenHeaderResponseResult.Serialization.cs Regenerates paging collection fallback.
ListWithContinuationTokenResult.Serialization.cs Regenerates paging collection fallback.
ListWithNextLinkResult.Serialization.cs Regenerates paging collection fallback.
ListWithStringNextLinkResult.Serialization.cs Regenerates paging collection fallback.
PageThing.Serialization.cs Regenerates page-item fallback.
RoundTripModel.Serialization.cs Regenerates required collection fallbacks.
XmlAdvancedModel.Serialization.cs Regenerates XML collection fallbacks.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix JSON round-trip NullReferenceException in C# models [http-client-csharp] Initialize omitted required collections during deserialization Sep 30, 2026

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 review overview

🟡 Changes recommended

The fallback condition incorrectly converts omitted required-nullable customized collections into empty collections.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@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.

Copilot review overview

🟡 Changes recommended

The requested XML, multipart, and dynamic optional concrete-list regression tests remain absent.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@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.

Copilot review overview

🟢 Approval recommended

The corrected behavior is consistently applied and covered across the affected serialization paths.

Review effort: Balanced
Findings: None

Resolved since last review (1)

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 review overview

🟢 Approval recommended

The implementation preserves nullability semantics and includes focused generated-output and runtime regression coverage.

Review effort: Balanced
Findings: None

private const string IsDefinedMethodName = "IsDefined";
private const string IsCollectionDefinedMethodName = "IsCollectionDefined";

public static ScopedApi<bool> IsCollectionDefined(ValueExpression collection)

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 this is a breaking change. Revert the modifier to public and just add a new internal overload

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.

Restored the public one-argument overload and kept the type-aware overload internal in 8d9e49a6. The targeted C# tests, generator build, and Cop checks pass.

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@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.

Copilot review overview

🟢 Approval recommended

The implementation preserves existing nullable semantics and includes focused baseline and runtime regression coverage.

Review effort: Balanced
Findings: None

: IsCollectionDefined(collection);
}

public static bool IsConcreteCollection(CSharpType type)

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 if this is only used in this type, lets make it private. If it's needed elsewhere in the assembly, make this internal

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.

IsConcreteCollection is also used by MrwSerializationTypeDefinition, so I changed it to internal rather than private in 532e7bf4. The generator build, 409 targeted tests, and Cop checks pass.

…assembly

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@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.

Copilot review overview

🟢 Approval recommended

The fallback logic is type-compatible and covered across omitted, nullable, explicit-null, serialization, and customization paths.

Review effort: Balanced
Findings: None

This branch has not been deployed

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

Labels

emitter:client:csharp Issue for the C# client emitter: @typespec/http-client-csharp

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[http-client-csharp] JSON round-trip throws NullReferenceException when a required collection is omitted

4 participants