Skip to content

Commit 249721b

Browse files
Re-enable source generator support for inaccessible [JsonInclude] members
The System.Text.Json source generator supports inaccessible members via UnsafeAccessor (net8+) or a reflection fallback (.NET Framework). Support for inaccessible members annotated with [JsonInclude] was intentionally disabled in #124650 because a workaround in the MCP SDK relied on the omission. That dependency has since been removed (modelcontextprotocol/csharp-sdk#1686), so this re-enables full support. - The parser no longer forces HasJsonInclude = false for inaccessible [JsonInclude] members and no longer reports SYSLIB1038. - The SYSLIB1038 diagnostic descriptor and its resx/xlf strings are removed; the diagnostic ID remains documented so it is never reused. - Behavior tests now assert full round-trip support uniformly across reflection and source-gen; the disabled-behavior source-gen overrides are removed and the UnsafeAccessors_PrivateProperties baselines are regenerated for both netcoreapp (UnsafeAccessor) and net462 (reflection). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent e6428cb commit 249721b

25 files changed

Lines changed: 65 additions & 531 deletions

src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,6 @@ internal static class DiagnosticDescriptors
6868
defaultSeverity: DiagnosticSeverity.Error,
6969
isEnabledByDefault: true);
7070

71-
public static DiagnosticDescriptor InaccessibleJsonIncludePropertiesNotSupported { get; } = DiagnosticDescriptorHelper.Create(
72-
id: "SYSLIB1038",
73-
title: new LocalizableResourceString(nameof(SR.InaccessibleJsonIncludePropertiesNotSupportedTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
74-
messageFormat: new LocalizableResourceString(nameof(SR.InaccessibleJsonIncludePropertiesNotSupportedFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),
75-
category: JsonConstants.SystemTextJsonSourceGenerationName,
76-
defaultSeverity: DiagnosticSeverity.Warning,
77-
isEnabledByDefault: true);
78-
7971
public static DiagnosticDescriptor PolymorphismNotSupported { get; } = DiagnosticDescriptorHelper.Create(
8072
id: "SYSLIB1039",
8173
title: new LocalizableResourceString(nameof(SR.FastPathPolymorphismNotSupportedTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)),

src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,12 +1986,6 @@ void AddMember(
19861986

19871987
AddPropertyWithConflictResolution(propertySpec, memberInfo, propertyIndex: properties.Count, ref state);
19881988
properties.Add(propertySpec);
1989-
1990-
// Note: ParsePropertyGenerationSpec intentionally does not mark inaccessible
1991-
// [JsonInclude] members as invalid for fast-path generation. Some callers rely
1992-
// on that omission to source-generate against experimental APIs without
1993-
// introducing new warnings until https://github.com/dotnet/runtime/issues/124889
1994-
// is completed.
19951989
}
19961990

19971991
bool PropertyIsOverriddenAndIgnored(IPropertySymbol property, Dictionary<string, ISymbol>? ignoredMembers)
@@ -2162,16 +2156,10 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
21622156
out bool isRequired,
21632157
out bool canUseGetter,
21642158
out bool canUseSetter,
2165-
out bool hasJsonIncludeButIsInaccessible,
21662159
out bool setterIsInitOnly,
21672160
out bool isGetterNonNullable,
21682161
out bool isSetterNonNullable);
21692162

2170-
if (hasJsonIncludeButIsInaccessible)
2171-
{
2172-
ReportDiagnostic(DiagnosticDescriptors.InaccessibleJsonIncludePropertiesNotSupported, memberInfo.GetLocation(), declaringType.Name, memberInfo.Name);
2173-
}
2174-
21752163
if (isExtensionData)
21762164
{
21772165
if (typeHasExtensionDataProperty)
@@ -2187,11 +2175,13 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
21872175
typeHasExtensionDataProperty = true;
21882176
}
21892177

2190-
if ((!canUseGetter && !canUseSetter && !hasJsonIncludeButIsInaccessible) ||
2178+
if ((!canUseGetter && !canUseSetter && !hasJsonInclude) ||
21912179
!IsSymbolAccessibleWithin(memberType, within: contextType))
21922180
{
21932181
// Skip the member if either of the two conditions hold
2194-
// 1. Member has no accessible getters or setters (but is not marked with JsonIncludeAttribute since we need to throw a runtime exception) OR
2182+
// 1. Member has no accessible getters or setters and is not annotated with
2183+
// JsonIncludeAttribute (inaccessible [JsonInclude] members are read/written
2184+
// using UnsafeAccessor or reflection) OR
21952185
// 2. The member type is not accessible within the generated context.
21962186
return null;
21972187
}
@@ -2244,10 +2234,7 @@ private bool IsValidDataExtensionPropertyType(ITypeSymbol type)
22442234
NumberHandling = numberHandling,
22452235
ObjectCreationHandling = objectCreationHandling,
22462236
Order = order,
2247-
// TODO: remove the inaccessibility check once https://github.com/dotnet/runtime/issues/124889
2248-
// is complete; some callers currently rely on this omission when source-generating
2249-
// against experimental APIs (tracking: https://github.com/dotnet/runtime/issues/88519).
2250-
HasJsonInclude = hasJsonInclude && !hasJsonIncludeButIsInaccessible,
2237+
HasJsonInclude = hasJsonInclude,
22512238
CanUseUnsafeAccessors = _knownSymbols.UnsafeAccessorAttributeType is not null
22522239
&& (memberInfo.ContainingType is not INamedTypeSymbol { IsGenericType: true }
22532240
|| _knownSymbols.SupportsGenericUnsafeAccessors),
@@ -2396,7 +2383,6 @@ private void ProcessMember(
23962383
out bool isRequired,
23972384
out bool canUseGetter,
23982385
out bool canUseSetter,
2399-
out bool hasJsonIncludeButIsInaccessible,
24002386
out bool isSetterInitOnly,
24012387
out bool isGetterNonNullable,
24022388
out bool isSetterNonNullable)
@@ -2406,7 +2392,6 @@ private void ProcessMember(
24062392
isRequired = false;
24072393
canUseGetter = false;
24082394
canUseSetter = false;
2409-
hasJsonIncludeButIsInaccessible = false;
24102395
isSetterInitOnly = false;
24112396
isGetterNonNullable = false;
24122397
isSetterNonNullable = false;
@@ -2429,10 +2414,6 @@ private void ProcessMember(
24292414
isAccessible = true;
24302415
canUseGetter = hasJsonInclude;
24312416
}
2432-
else
2433-
{
2434-
hasJsonIncludeButIsInaccessible = hasJsonInclude;
2435-
}
24362417
}
24372418

24382419
if (propertyInfo.SetMethod is { } setMethod)
@@ -2449,10 +2430,6 @@ private void ProcessMember(
24492430
isAccessible = true;
24502431
canUseSetter = hasJsonInclude;
24512432
}
2452-
else
2453-
{
2454-
hasJsonIncludeButIsInaccessible = hasJsonInclude;
2455-
}
24562433
}
24572434
else
24582435
{
@@ -2478,10 +2455,6 @@ private void ProcessMember(
24782455
canUseGetter = hasJsonInclude;
24792456
canUseSetter = hasJsonInclude && !isReadOnly;
24802457
}
2481-
else
2482-
{
2483-
hasJsonIncludeButIsInaccessible = hasJsonInclude;
2484-
}
24852458

24862459
fieldInfo.ResolveNullabilityAnnotations(out isGetterNonNullable, out isSetterNonNullable);
24872460
break;

src/libraries/System.Text.Json/gen/Resources/Strings.resx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,6 @@
153153
<data name="DataExtensionPropertyInvalidTitle" xml:space="preserve">
154154
<value>Data extension property type invalid.</value>
155155
</data>
156-
<data name="InaccessibleJsonIncludePropertiesNotSupportedTitle" xml:space="preserve">
157-
<value>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</value>
158-
</data>
159-
<data name="InaccessibleJsonIncludePropertiesNotSupportedFormat" xml:space="preserve">
160-
<value>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</value>
161-
</data>
162156
<data name="FastPathPolymorphismNotSupportedTitle" xml:space="preserve">
163157
<value>'JsonDerivedTypeAttribute' is not supported in 'JsonSourceGenerationMode.Serialization'.</value>
164158
</data>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">Atribut JsonDerivedTypeAttribute se v JsonSourceGenerationMode.Serialization nepodporuje.</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">Člen {0}.{1} má anotaci od JsonIncludeAttribute, ale není pro zdrojový generátor viditelný.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">Nepřístupné vlastnosti anotované s JsonIncludeAttribute se v režimu generování zdroje nepodporují.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">Typ JsonConverterAttribute {0} specifikovaný u členu {1} není typem konvertoru nebo neobsahuje přístupný konstruktor bez parametrů.</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">„JsonDerivedTypeAttribute“ wird in „JsonSourceGenerationMode.Serialization“ nicht unterstützt.</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">Der Member "{0}. {1}" wurde mit dem JsonIncludeAttribute versehen, ist jedoch für den Quellgenerator nicht sichtbar.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">Nicht zugängliche Eigenschaften, die mit dem JsonIncludeAttribute versehen sind, werden im Quellgenerierungsmodus nicht unterstützt.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">Der für den Member "{1}" angegebene JsonConverterAttribute-Typ "{0}" ist kein Konvertertyp oder enthält keinen parameterlosen Konstruktor, auf den zugegriffen werden kann.</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">\"JsonDerivedTypeAttribute\" no se admite en \"JsonSourceGenerationMode.Serialization\".</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">El miembro '{0}.{1}' se ha anotado con JsonIncludeAttribute, pero no es visible para el generador de origen.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">Las propiedades inaccesibles anotadas con JsonIncludeAttribute no se admiten en el modo de generación de origen.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">El tipo “JsonConverterAttribute” “{0}” especificado en el miembro “{1}” no es un tipo de convertidor o no contiene un constructor sin parámetros accesible.</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">« JsonDerivedTypeAttribute » n’est pas pris en charge dans « JsonSourceGenerationMode.Serialization ».</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">Le membre '{0}.{1}' a été annoté avec JsonIncludeAttribute mais n’est pas visible pour le générateur source.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">Les propriétés inaccessibles annotées avec JsonIncludeAttribute ne sont pas prises en charge en mode de génération de source.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">Le type 'JsonConverterAttribute' '{0}' spécifié sur le membre '{1}' n’est pas un type convertisseur ou ne contient pas de constructeur sans paramètre accessible.</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">'JsonDerivedTypeAttribute' non è supportato in 'JsonSourceGenerationMode.Serialization'.</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">Il membro ' {0}.{1}' è stato annotato con JsonIncludeAttribute ma non è visibile al generatore di origine.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">Le proprietà inaccessibili annotate con JsonIncludeAttribute non sono supportate nella modalità di generazione di origine.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">Il tipo 'JsonConverterAttribute' '{0}' specificato nel membro '{1}' non è un tipo di convertitore o non contiene un costruttore senza parametri accessibile.</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">'JsonDerivedTypeAttribute' は 'JsonSourceGenerationMode.Serialization' ではサポートされていません。</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">メンバー '{0}.{1}' には、JsonIncludeAttribute で注釈が付けられていますが、ソース ジェネレーターには表示されません。</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">JsonIncludeAttribute で注釈が付けられたアクセスできないプロパティは、ソース生成モードではサポートされていません。</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">メンバー '{1}' で指定されている 'JsonConverterAttribute' 型 '{0}' はコンバーター型ではないか、アクセス可能なパラメーターなしのコンストラクターを含んでいません。</target>

src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,6 @@
5252
<target state="translated">'JsonSourceGenerationMode.Serialization'에서는 'JsonDerivedTypeAttribute'가 지원되지 않습니다.</target>
5353
<note />
5454
</trans-unit>
55-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedFormat">
56-
<source>The member '{0}.{1}' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.</source>
57-
<target state="translated">멤버 '{0}.{1}'이(가) JsonIncludeAttribute로 주석 처리되었지만 원본 생성기에는 표시되지 않습니다.</target>
58-
<note />
59-
</trans-unit>
60-
<trans-unit id="InaccessibleJsonIncludePropertiesNotSupportedTitle">
61-
<source>Inaccessible properties annotated with the JsonIncludeAttribute are not supported in source generation mode.</source>
62-
<target state="translated">JsonIncludeAttribute로 주석 처리된 액세스할 수 없는 속성은 원본 생성 모드에서 지원되지 않습니다.</target>
63-
<note />
64-
</trans-unit>
6555
<trans-unit id="JsonConverterAttributeInvalidTypeMessageFormat">
6656
<source>The 'JsonConverterAttribute' type '{0}' specified on member '{1}' is not a converter type or does not contain an accessible parameterless constructor.</source>
6757
<target state="translated">'{1}' 멤버에 지정된 'JsonConverterAttribute' 형식 '{0}'이(가) 변환기 형식이 아니거나 액세스 가능한 매개 변수가 없는 생성자를 포함하지 않습니다.</target>

0 commit comments

Comments
 (0)