Skip to content

Initialize non-nullable required unwrapped XML list properties to empty collections during deserialization - #9968

Merged
Jorge Rangel (jorgerangel-msft) merged 4 commits into
mainfrom
copilot/always-initialize-non-optional-items
Mar 10, 2026
Merged

Jorge Rangel (jorgerangel-msft) merged 4 commits into
mainfrom
copilot/always-initialize-non-optional-items

Conversation

Copilot AI commented Mar 9, 2026 •

Copy link
Copy Markdown
Contributor

When a service returns an empty XML wrapper element (e.g., <Blobs />), unwrapped list properties deserialize to null because the list is only initialized inside the foreach loop upon matching a child element. For required, non-nullable properties this should yield an empty list.

Changes

  • MrwSerializationTypeDefinition.cs: In GetPropertyVariableDeclarations(), added IsXmlUnwrappedRequiredCollection helper that initializes unwrapped, required, non-nullable collection properties with new List<T>() at variable declaration time instead of default
  • MrwSerializationTypeDefinition.Xml.cs: In CreateXmlDeserializeListAssignment(), added isPreInitialized parameter to skip the redundant if (list == null) null-check when the list is already initialized at declaration time
  • XmlDeserializationTests.cs: Added XmlDeserializationMethodHandlesOptionalUnwrappedListProperty test using FilteredMethodsTypeProvider to verify optional properties retain the null-check and are not affected
  • Test data / regenerated code: Updated expected output and regenerated XmlAdvancedModel.Serialization.cs

Generated output

// Variable initialized at declaration instead of default
IList<string> colors = new List<string>();
IDictionary<string, BinaryData> additionalBinaryDataProperties = new ChangeTrackingDictionary<string, BinaryData>();

foreach (var child in element.Elements())
{
    string localName = child.Name.LocalName;
    if (localName == "colors")
    {
        // No null check needed — colors is already initialized
        colors.Add((string)child);
        continue;
    }
}
return new TestXmlModel(colors, additionalBinaryDataProperties);
Original prompt

This section details on the original issue you should resolve

<issue_title>Always Initialize Non-Optional Unwrapped Items in XML Deserialization</issue_title>
<issue_description>Consider this tsp:

@Xml.name("EnumerationResults")
model ListBlobsResponse {
  /** The service endpoint. */
  @Xml.attribute
  @Xml.name("ServiceEndpoint")
  serviceEndpoint: string;

  /** The container name. */
  @Xml.attribute
  @Xml.name("ContainerName")
  containerName: string;

  /** The prefix of the blobs. */
  @Xml.name("Prefix") prefix?: string;

  /** The marker of the blobs. */
  @Xml.name("Marker") marker?: string;

  /** The max results of the blobs. */
  @Xml.name("MaxResults") maxResults?: int32;

  /** The blob segment. */
  @Xml.name("Blobs")
  segment: BlobFlatListSegment;

  /** The next marker of the blobs. */
  @continuationToken
  @Xml.name("NextMarker")
  nextMarker?: string;
}

/** The blob flat list segment. */
model BlobFlatListSegment {
  /** The blob items. */
  @pageItems
  @Xml.name("Blob")
  @Xml.unwrapped
  blobItems: BlobItem[];
}

The service can returns <Blobs /> and the current XML deserialization code will deserialize segment into null since there are no Blob elements in Blobs. Since blobItems is unwrapped and non-nullable, we should be initializing it to an empty list by default.

We should update the xml deserialization to initialize collection properties to an empty collection when they are non-nullable, required, and unwrapped.</issue_description>

Comments on the Issue (you are Copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

…o empty collections during deserialization

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 Mar 9, 2026
Copilot AI changed the title [WIP] Fix non-optional unwrapped items in XML deserialization Initialize non-nullable required unwrapped XML list properties to empty collections during deserialization Mar 9, 2026
…VariableDeclarations and use FilteredMethodsTypeProvider in tests

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>

Copilot AI commented Mar 9, 2026

Copy link
Copy Markdown
Contributor Author

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • telemetry.astro.build
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node node /home/REDACTED/work/typespec/typespec/website/node_modules/.bin/../astro/astro.js build sh n-sc�� ebsite/src/conte--llmstxt sh /.bin/node import @typespecnode (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@pkg-pr-new

pkg-pr-new Bot commented Mar 9, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

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

commit: 10de392

…ctions and restore original test structure

Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com>
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Mar 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to no response for status checks Mar 10, 2026
Merged via the queue into main with commit a5cd673 Mar 10, 2026
24 checks passed
@jorgerangel-msft
Jorge Rangel (jorgerangel-msft) deleted the copilot/always-initialize-non-optional-items branch March 10, 2026 16:31
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.

Always Initialize Non-Optional Unwrapped Items in XML Deserialization

3 participants