Add MA0222 and MA0223 to require the System.Text.Json Respect* options to be configured - #1432
Merged
meziantou merged 2 commits intoSep 7, 2026
Merged
Conversation
…equiredConstructorParameters options System.Text.Json ignores the nullable annotations of the types it (de)serializes and treats every constructor parameter as optional, unless RespectNullableAnnotations and RespectRequiredConstructorParameters are configured. Both were introduced in .NET 9 and default to false for backward compatibility, so a JsonSerializerContext that does not configure them silently produces instances whose non-nullable members are null, or that were built from an incomplete payload. MA0222 and MA0223 report the JsonSerializerContext whose [JsonSourceGenerationOptions] attribute does not set the corresponding option, including the ones that have no attribute at all. They require the option to be set, not to be set to true: keeping the legacy behavior is a valid choice, as long as it is explicit. JsonSerializerDefaults.Strict, introduced in .NET 10, sets both options, and a named argument wins over it. Both rules are disabled by default, as they require every context to configure the options. The code fixer sets the option to true, adding the attribute when the context has none. The diagnostic reported on a context without the attribute skips the declaration the source generator emits, so it never points at generated code.
…et framework The tests pinned .NET 9, the version that introduced the options, so they never exercised the newer ones. They now use the target framework the harness provides by default, and only lower it when they have a reason to: the .NET 8 test asserting that nothing is reported when the options do not exist, and the older versions of Roslyn, whose test host cannot load the source generators shipped with the latest .NET.
meziantou
enabled auto-merge (squash)
September 7, 2026 05:22
meziantou
deleted the
feature/json-source-generation-options-rule-006f46
branch
September 7, 2026 05:24
This was referenced Sep 7, 2026
Bump Meziantou.Analyzer from 3.0.139 to 3.0.224
Analogy-LogViewer/Analogy.LogViewer.NLog.Targets#564
Closed
Closed
Bump Meziantou.Analyzer from 3.0.139 to 3.0.224
Analogy-LogViewer/Analogy.AspNetCore.LogProvider#548
Closed
Closed
Closed
Closed
This was referenced Sep 16, 2026
Open
Open
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two new rules, one per option, both disabled by default:
RespectNullableAnnotationsRespectRequiredConstructorParametersThey report a
JsonSerializerContextwhose[JsonSourceGenerationOptions]attribute does not set the corresponding option, including the contexts that have no attribute at all. A code fixer sets the option totrue, adding the attribute when the context has none.Why
System.Text.Jsonignores the nullable annotations of the types it (de)serializes, and treats every constructor parameter as optional.RespectNullableAnnotationsandRespectRequiredConstructorParameters(both .NET 9) enable those validations, but default tofalsefor backward compatibility — so a context that never mentions them silently produces instances whose non-nullable members arenull, or that were built from an incomplete payload.Notes for the reviewer
true.RespectNullableAnnotations = falseis a deliberate choice and satisfies MA0222 exactly as= truedoes. The rules are about making the decision explicit; the fixer is the one that opts fortrue.JsonSerializerDefaults.Strictcounts as setting both. It configures them through the constructor, so[JsonSourceGenerationOptions(JsonSerializerDefaults.Strict)]stays clean, and a named argument still wins over it.WebandGeneraldo not touch the options and still report. Verified against the real generator thatStrictsets both, and that an explicitRespectNullableAnnotations = falseoverrides it.ValidateFixedAddressValueTypeAttributeUsageAnalyzer(MA0207/MA0208) precedent — the symbol lookups and theJsonSerializerContextwalk are shared, so two analyzer types would double the per-compilation cost for the same work. Each rule is still gated on its own property existing on the attribute type, so they can diverge across target frameworks..g.cs.Tests
JsonSourceGenerationOptionsAnalyzerTestsdrives the real System.Text.Json source generator (UseFrameworkSourceGenerators), without which theJsonSerializerContextsnippets would not compile.Reference assemblies are pinned to
Net90(the minimum version with the options) rather than the default pack, because the newer generators cannot be loaded by the older Roslyn test hosts. TheJsonSerializerDefaults.Strictcases needNet100, whose generators require Roslyn 4.14+, so they are behind#if ROSLYN_4_14_OR_GREATER.dotnet run --project src/DocumentationGeneratorexits 0 on a re-run