Skip to content

.NET: Fix JSON arrays of objects parsed as empty records when no schema is defined#4199

Merged
crickman merged 2 commits into
microsoft:mainfrom
LEDazzio01:fix/4195-json-array-empty-records
Feb 25, 2026
Merged

.NET: Fix JSON arrays of objects parsed as empty records when no schema is defined#4199
crickman merged 2 commits into
microsoft:mainfrom
LEDazzio01:fix/4195-json-array-empty-records

Conversation

@LEDazzio01

Copy link
Copy Markdown
Contributor

Motivation and Context

Fixes #4195 — JSON arrays of objects are parsed as empty records when no schema is defined in declarative workflows.

When an InvokeAzureAgent action returns a JSON object containing an array of objects, and the output is captured via responseObject, all nested object properties are silently dropped. Each object in the array becomes {}. Subsequent Foreach iteration over the array crashes with an unhandled workflow failure.

Description

Root cause: In JsonDocumentExtensions.cs, the ParseTable method's DetermineElementType() function creates a schema-bound VariableType with an empty (non-null) schema when targetType.Schema is null:

// Before (broken)
JsonValueKind.Object => VariableType.Record(targetType.Schema?.Select(kvp => (kvp.Key, kvp.Value)) ?? []),

When targetType.Schema is null, the ?? [] fallback passes an empty collection to VariableType.Record(), creating a VariableType with Schema set to an empty FrozenDictionary (non-null, count = 0). Downstream, ParseRecord checks targetType.Schema is null and takes the ParseSchema path (which iterates over zero fields), silently discarding all JSON properties.

Fix: Check targetType.HasSchema (which correctly handles empty schemas) and fall back to VariableType.RecordType when no schema is defined:

// After (fixed)
JsonValueKind.Object => targetType.HasSchema
    ? VariableType.Record(targetType.Schema!.Select(kvp => (kvp.Key, kvp.Value)))
    : VariableType.RecordType,

This ensures ParseRecord takes the dynamic ParseValues() path that preserves all JSON properties.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? No — this is a bug fix that restores expected behavior.

…ords

When parsing JSON arrays containing objects without a predefined schema,
`DetermineElementType()` was creating a `VariableType` with an empty
(non-null) schema via `targetType.Schema?.Select(...) ?? []`. This caused
`ParseRecord` to take the schema-based parsing path, iterating over zero
schema fields and silently discarding all JSON properties.

The fix checks `targetType.HasSchema` and falls back to
`VariableType.RecordType` (which has `Schema = null`) when no schema is
defined, ensuring `ParseRecord` takes the dynamic `ParseValues()` path
that preserves all JSON properties.

Closes #4195
Copilot AI review requested due to automatic review settings February 23, 2026 23:01
@LEDazzio01

Copy link
Copy Markdown
Contributor Author

I have sole ownership of intellectual property rights to my Submissions and I am not making Submissions in the course of work for my employer.

@markwallace-microsoft markwallace-microsoft added .NET Usage: [Issues, PRs], Target: .Net workflows Usage: [Issues, PRs], Target: Workflows labels Feb 23, 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.

Pull request overview

Fixes a declarative workflow JSON parsing bug where arrays of objects could be inferred as “empty-schema records,” causing nested object properties to be dropped when no schema is defined.

Changes:

  • Updates ParseTable element-type inference to use VariableType.RecordType when the target list type has no schema, avoiding creation of an empty (non-null) schema.
  • Uses targetType.HasSchema to decide when to propagate a schema into inferred record element types.

@crickman crickman requested review from crickman February 24, 2026 17:28
@crickman crickman self-assigned this Feb 24, 2026
@crickman crickman moved this to In Review in Agent Framework Feb 24, 2026
@crickman crickman added the bug Usage: [Issues], Target: all issues (Legacy, prefer issue type: bug) label Feb 24, 2026
…ing (#4195)

Add two regression tests to JsonDocumentExtensionsTests:

1. ParseRecord_ObjectWithArrayOfObjects_NoSchema_PreservesNestedProperties
   - Parses a JSON object containing an array of objects using
     VariableType.RecordType (no schema) and verifies that nested
     object properties (name, role) are preserved in each element.
   - This is the exact scenario from issue #4195 where objects in
     arrays were being returned as empty dictionaries.

2. ParseList_ArrayOfObjects_NoSchema_PreservesProperties
   - Parses a JSON array of objects directly via ParseList with
     VariableType.ListType (no schema) and verifies all properties
     are preserved.

Both tests follow the existing Arrange/Act/Assert pattern and would
have failed before the DetermineElementType() fix (empty dictionaries
instead of populated ones).
@LEDazzio01

Copy link
Copy Markdown
Contributor Author

@crickman — Unit tests are ready! I just pushed 7f3182f with two regression tests added to JsonDocumentExtensionsTests.cs:

  1. ParseRecord_ObjectWithArrayOfObjects_NoSchema_PreservesNestedProperties — The exact bug repro from .NET: [Bug]: Declarative workflow - JSON arrays of objects parsed as empty records when no schema is defined #4195: parses { "items": [ {"name":"Alice","role":"Engineer"}, ... ] } with VariableType.RecordType (no schema) and asserts all nested properties are preserved (would have returned [{}, {}, {}] before the fix).

  2. ParseList_ArrayOfObjects_NoSchema_PreservesProperties — Exercises ParseList directly with VariableType.ListType (no schema) on an array of objects, verifying properties aren't dropped during element-type inference.

Both follow the existing Arrange/Act/Assert pattern and reference the issue in their XML doc comments. Let me know if you'd like any adjustments!

@crickman crickman requested a review from peibekwe February 25, 2026 00:31
@crickman crickman added this pull request to the merge queue Feb 25, 2026
Merged via the queue into microsoft:main with commit 2ad0caf Feb 25, 2026
18 checks passed
@moonbox3 moonbox3 added declarative Usage: [Issues, PRs], Target: declarative agents and workflows and removed declarative-workflow labels Jun 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Usage: [Issues], Target: all issues (Legacy, prefer issue type: bug) declarative Usage: [Issues, PRs], Target: declarative agents and workflows .NET Usage: [Issues, PRs], Target: .Net workflows Usage: [Issues, PRs], Target: Workflows

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

.NET: [Bug]: Declarative workflow - JSON arrays of objects parsed as empty records when no schema is defined

6 participants