镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

[release/11.0] Validate custom union type classifier results before deserialization - #137079

Merged
ViveliDuCh merged 1 commit into
release/11.0from
backport/pr-136226-to-release/11.0
Nov 10, 2026
Merged

ViveliDuCh merged 1 commit into
release/11.0from
backport/pr-136226-to-release/11.0

Conversation

@github-actions

@github-actions github-actions Bot commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Backport of #136226 to release/11.0

/cc @eiriktsarpalis

Customer Impact

  • Customer reported
  • Found internally

The newly introduced type classifier infrastructure intended to support union type deserialization did not include any validation for user-defined classifier delegates returning invalid types.

Regression

  • Yes
  • No

Testing

Added testing covering the missed scenario.

Risk

Low. Adds a straightforward validation step after invoking the user-defined delegate.

…136226)

<!-- -->

`JsonUnionConverter<TUnion>` currently resolves metadata and invokes the
converter for any non-null type returned by a custom classifier. Unlike
polymorphic deserialization, it does not check the result against the
configured case types before dispatch.

Cache the final `UnionCases` in a `HashSet<Type>` for classifier-backed
unions and throw `JsonException` for undeclared results before resolving
their metadata. Membership is exact: an undeclared subtype is rejected
even when assignable to a declared case. Default classification and JSON
null handling are unchanged.

The shared regression tests cover invalid and undeclared results,
undeclared subtypes, cases added or removed through contract
customization, and declared nullable cases. The rejection regressions
were reproduced before the fix. All 154 new cases pass across reflection
and source-generated serializers targeting `net11.0` and `net481`. The
affected union, structural-classifier, and polymorphism test groups also
pass: 7,676 reflection cases and 3,284 source-generation cases per
target, with 8 existing skips per source-generation run. Release builds
pass for all four library target frameworks.

`HashSet<Type>` avoids adding a `System.Collections.Immutable` product
dependency. Local lookup benchmarks found `FrozenSet<Type>` faster for
2-4 entries, but not consistently faster for 8-16 entries. End-to-end
BenchmarkDotNet measurements on a Windows x64 Hyper-V VM were:

| Operation | Before | After | Allocated, unchanged |
| --- | ---: | ---: | ---: |
| Scalar union deserialization | 105.5 ns | 108.3 ns | 48 B |
| Object union deserialization | 429.8 ns | 425.9 ns | 568 B |

The scalar case adds approximately 3% overhead; the object case is
approximately unchanged in this local run.

> [!NOTE]
> This pull request was generated with GitHub Copilot.

Copilot-Session: 60a19e82-e4d1-4d77-a6ed-cd039cd02cab
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
12 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.

@eiriktsarpalis

Copy link
Copy Markdown
Member

Approved via email.

@eiriktsarpalis eiriktsarpalis added Servicing-approved Approved for servicing release and removed api-approved API was approved in API review, it can be implemented labels Nov 6, 2026
@eiriktsarpalis

Copy link
Copy Markdown
Member

/ba-g test failure is unrelated

@ViveliDuCh
ViveliDuCh merged commit 80f07ae into release/11.0 Nov 10, 2026
107 of 114 checks passed
@ViveliDuCh
ViveliDuCh deleted the backport/pr-136226-to-release/11.0 branch November 10, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-System.Text.Json Servicing-approved Approved for servicing release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants