diff --git a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs
index 84ffc3d5414b34..45f11a41063ccb 100644
--- a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs
+++ b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs
@@ -30,11 +30,6 @@ sealed class JsonSourceGenerationOptionsAttribute : JsonAttribute
///
public bool IgnoreReadOnlyProperties { get; set; }
- ///
- /// Specifies whether to ignore custom converters provided at run time.
- ///
- public bool IgnoreRuntimeCustomConverters { get; set; }
-
///
/// Specifies whether to include fields for serialization and deserialization.
///
diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
index 131e08d0d0c2bf..217aed6f271c40 100644
--- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
+++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
@@ -23,13 +23,18 @@ private sealed partial class Emitter
private const string CtorParamInitMethodNameSuffix = "CtorParamInit";
private const string DefaultOptionsStaticVarName = "s_defaultOptions";
private const string DefaultContextBackingStaticVarName = "s_defaultContext";
+ private const string ElementInfoPropName = "ElementInfo";
internal const string GetConverterFromFactoryMethodName = "GetConverterFromFactory";
+ private const string InfoVarName = "info";
private const string JsonSerializerContextName = "JsonSerializerContext";
internal const string JsonContextVarName = "jsonContext";
+ private const string KeyInfoPropName = "KeyInfo";
+ private const string NumberHandlingPropName = "NumberHandling";
+ private const string ObjectCreatorPropName = "ObjectCreator";
private const string OptionsInstanceVariableName = "Options";
private const string PropInitMethodNameSuffix = "PropInit";
private const string RuntimeCustomConverterFetchingMethodName = "GetRuntimeProvidedCustomConverter";
- private const string SerializeMethodNameSuffix = "Serialize";
+ private const string SerializeHandlerPropName = "SerializeHandler";
private const string ValueVarName = "value";
private const string WriterVarName = "writer";
@@ -55,6 +60,7 @@ private sealed partial class Emitter
private const string Utf8JsonWriterTypeRef = "global::System.Text.Json.Utf8JsonWriter";
private const string JsonConverterTypeRef = "global::System.Text.Json.Serialization.JsonConverter";
private const string JsonConverterFactoryTypeRef = "global::System.Text.Json.Serialization.JsonConverterFactory";
+ private const string JsonCollectionInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues";
private const string JsonIgnoreConditionTypeRef = "global::System.Text.Json.Serialization.JsonIgnoreCondition";
private const string JsonNumberHandlingTypeRef = "global::System.Text.Json.Serialization.JsonNumberHandling";
private const string JsonSerializerContextTypeRef = "global::System.Text.Json.Serialization.JsonSerializerContext";
@@ -62,6 +68,7 @@ private sealed partial class Emitter
private const string JsonObjectInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues";
private const string JsonParameterInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues";
private const string JsonPropertyInfoTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo";
+ private const string JsonPropertyInfoValuesTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues";
private const string JsonTypeInfoTypeRef = "global::System.Text.Json.Serialization.Metadata.JsonTypeInfo";
private const string NotSupportedExceptionTypeRef = "global::System.NotSupportedException";
@@ -416,37 +423,37 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec)
string numberHandlingArg = $"{GetNumberHandlingAsStr(typeGenerationSpec.NumberHandling)}";
- string serializeFuncNamedArg;
+ string serializeHandlerValue;
- string? serializeFuncSource;
+ string? serializeHandlerSource;
if (!typeGenerationSpec.GenerateSerializationLogic)
{
- serializeFuncSource = null;
- serializeFuncNamedArg = "serializeFunc: null";
+ serializeHandlerSource = null;
+ serializeHandlerValue = "null";
}
else
{
- serializeFuncSource = typeGenerationSpec.ClassType == ClassType.Enumerable
+ serializeHandlerSource = typeGenerationSpec.ClassType == ClassType.Enumerable
? GenerateFastPathFuncForEnumerable(typeGenerationSpec)
: GenerateFastPathFuncForDictionary(typeGenerationSpec);
- serializeFuncNamedArg = $"serializeFunc: {typeGenerationSpec.FastPathSerializeMethodName}";
+ serializeHandlerValue = $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}";
}
CollectionType collectionType = typeGenerationSpec.CollectionType;
string typeRef = typeGenerationSpec.TypeRef;
- string createObjectFuncArg;
+ string objectCreatorValue;
if (typeGenerationSpec.RuntimeTypeRef != null)
{
- createObjectFuncArg = $"createObjectFunc: () => new {typeGenerationSpec.RuntimeTypeRef}()";
+ objectCreatorValue = $"() => new {typeGenerationSpec.RuntimeTypeRef}()";
}
else
{
- createObjectFuncArg = typeGenerationSpec.ConstructionStrategy == ObjectConstructionStrategy.ParameterlessConstructor
- ? $"createObjectFunc: () => new {typeRef}()"
- : "createObjectFunc: null";
+ objectCreatorValue = typeGenerationSpec.ConstructionStrategy == ObjectConstructionStrategy.ParameterlessConstructor
+ ? $"() => new {typeRef}()"
+ : "null";
}
string collectionInfoCreationPrefix = collectionType switch
@@ -455,15 +462,15 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec)
CollectionType.ICollectionOfT => $"{JsonMetadataServicesTypeRef}.CreateICollectionInfo<",
CollectionType.StackOfT => $"{JsonMetadataServicesTypeRef}.CreateStackInfo<",
CollectionType.QueueOfT => $"{JsonMetadataServicesTypeRef}.CreateQueueInfo<",
- CollectionType.Stack => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<",
- CollectionType.Queue => $"{JsonMetadataServicesTypeRef}.CreateStackOrQueueInfo<",
+ CollectionType.Stack => $"{JsonMetadataServicesTypeRef}.CreateStackInfo<",
+ CollectionType.Queue => $"{JsonMetadataServicesTypeRef}.CreateQueueInfo<",
CollectionType.IEnumerableOfT => $"{JsonMetadataServicesTypeRef}.CreateIEnumerableInfo<",
CollectionType.IDictionaryOfTKeyTValue => $"{JsonMetadataServicesTypeRef}.CreateIDictionaryInfo<",
_ => $"{JsonMetadataServicesTypeRef}.Create{collectionType}Info<"
};
- string dictInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}";
- string enumerableInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}";
+ string dictInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {keyTypeCompilableName!}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName}";
+ string enumerableInfoCreationPrefix = $"{collectionInfoCreationPrefix}{typeRef}, {valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName}";
string immutableCollectionCreationSuffix = $"createRangeFunc: {typeGenerationSpec.ImmutableCollectionBuilderName}";
string collectionTypeInfoValue;
@@ -471,23 +478,23 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec)
switch (collectionType)
{
case CollectionType.Array:
- collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{valueTypeCompilableName}>({OptionsInstanceVariableName}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+ collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{valueTypeCompilableName}>({OptionsInstanceVariableName}, {InfoVarName})";
break;
case CollectionType.IEnumerable:
case CollectionType.IList:
- collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+ collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName})";
break;
case CollectionType.Stack:
case CollectionType.Queue:
string addMethod = collectionType == CollectionType.Stack ? "Push" : "Enqueue";
string addFuncNamedArg = $"addFunc: (collection, {ValueVarName}) => collection.{addMethod}({ValueVarName})";
- collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg}, {addFuncNamedArg})";
+ collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName}, {addFuncNamedArg})";
break;
case CollectionType.ImmutableEnumerable:
collectionTypeInfoValue = $"{enumerableInfoCreationPrefix}, {immutableCollectionCreationSuffix})";
break;
case CollectionType.IDictionary:
- collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {createObjectFuncArg}, {keyTypeMetadataPropertyName!}, {valueTypeMetadataPropertyName}, {numberHandlingArg}, {serializeFuncNamedArg})";
+ collectionTypeInfoValue = $"{collectionInfoCreationPrefix}{typeRef}>({OptionsInstanceVariableName}, {InfoVarName})";
break;
case CollectionType.Dictionary:
case CollectionType.IDictionaryOfTKeyTValue:
@@ -502,9 +509,19 @@ private string GenerateForCollection(TypeGenerationSpec typeGenerationSpec)
break;
}
- string metadataInitSource = @$"_{typeGenerationSpec.TypeInfoPropertyName} = {collectionTypeInfoValue};";
+ string metadataInitSource = @$"{JsonCollectionInfoValuesTypeRef}<{typeRef}> {InfoVarName} = new {JsonCollectionInfoValuesTypeRef}<{typeRef}>()
+ {{
+ {ObjectCreatorPropName} = {objectCreatorValue},
+ {KeyInfoPropName} = {keyTypeMetadataPropertyName!},
+ {ElementInfoPropName} = {valueTypeMetadataPropertyName},
+ {NumberHandlingPropName} = {numberHandlingArg},
+ {SerializeHandlerPropName} = {serializeHandlerValue}
+ }};
+
+ _{typeGenerationSpec.TypeInfoPropertyName} = {collectionTypeInfoValue};
+";
- return GenerateForType(typeGenerationSpec, metadataInitSource, serializeFuncSource);
+ return GenerateForType(typeGenerationSpec, metadataInitSource, serializeHandlerSource);
}
private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerationSpec)
@@ -555,7 +572,7 @@ private string GenerateFastPathFuncForEnumerable(TypeGenerationSpec typeGenerati
{WriterVarName}.WriteEndArray();";
return GenerateFastPathFuncForType(
- typeGenerationSpec.FastPathSerializeMethodName,
+ $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}",
typeGenerationSpec.TypeRef,
serializationLogic,
typeGenerationSpec.CanBeNull);
@@ -599,7 +616,7 @@ private string GenerateFastPathFuncForDictionary(TypeGenerationSpec typeGenerati
{WriterVarName}.WriteEndObject();";
return GenerateFastPathFuncForType(
- typeGenerationSpec.FastPathSerializeMethodName,
+ $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}",
typeGenerationSpec.TypeRef,
serializationLogic,
typeGenerationSpec.CanBeNull);
@@ -641,23 +658,23 @@ private string GenerateForObject(TypeGenerationSpec typeMetadata)
if (typeMetadata.GenerateSerializationLogic)
{
serializeFuncSource = GenerateFastPathFuncForObject(typeMetadata);
- serializeMethodName = $"{typeFriendlyName}{SerializeMethodNameSuffix}";
+ serializeMethodName = $"{typeFriendlyName}{SerializeHandlerPropName}";
}
const string ObjectInfoVarName = "objectInfo";
string genericArg = typeMetadata.TypeRef;
string objectInfoInitSource = $@"{JsonObjectInfoValuesTypeRef}<{genericArg}> {ObjectInfoVarName} = new {JsonObjectInfoValuesTypeRef}<{genericArg}>()
- {{
- ObjectCreator = {creatorInvocation},
- ObjectWithParameterizedConstructorCreator = {parameterizedCreatorInvocation},
- PropertyMetadataInitializer = {propInitMethodName},
- ConstructorParameterMetadataInitializer = {ctorParamMetadataInitMethodName},
- NumberHandling = {GetNumberHandlingAsStr(typeMetadata.NumberHandling)},
- SerializeHandler = {serializeMethodName}
- }};
+ {{
+ {ObjectCreatorPropName} = {creatorInvocation},
+ ObjectWithParameterizedConstructorCreator = {parameterizedCreatorInvocation},
+ PropertyMetadataInitializer = {propInitMethodName},
+ ConstructorParameterMetadataInitializer = {ctorParamMetadataInitMethodName},
+ {NumberHandlingPropName} = {GetNumberHandlingAsStr(typeMetadata.NumberHandling)},
+ {SerializeHandlerPropName} = {serializeMethodName}
+ }};
- _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.CreateObjectInfo<{typeMetadata.TypeRef}>({OptionsInstanceVariableName}, {ObjectInfoVarName});";
+ _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.CreateObjectInfo<{typeMetadata.TypeRef}>({OptionsInstanceVariableName}, {ObjectInfoVarName});";
string additionalSource = @$"{propMetadataInitFuncSource}{serializeFuncSource}{ctorParamMetadataInitFuncSource}";
@@ -705,63 +722,66 @@ private string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenerationSpe
? "null"
: $"{JsonContextVarName}.{memberTypeMetadata.TypeInfoPropertyName}";
- string typeTypeInfoNamedArg = $"propertyTypeInfo: {memberTypeFriendlyName}";
-
- string jsonPropertyNameNamedArg = memberMetadata.JsonPropertyName != null
- ? @$"jsonPropertyName: ""{memberMetadata.JsonPropertyName}"""
- : "jsonPropertyName: null";
+ string jsonPropertyNameValue = memberMetadata.JsonPropertyName != null
+ ? @$"""{memberMetadata.JsonPropertyName}"""
+ : "null";
- string getterNamedArg = memberMetadata switch
+ string getterValue = memberMetadata switch
{
- { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "getter: null",
- { CanUseGetter: true } => $"getter: static (obj) => (({declaringTypeCompilableName})obj).{clrPropertyName}",
+ { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null",
+ { CanUseGetter: true } => $"static (obj) => (({declaringTypeCompilableName})obj).{clrPropertyName}",
{ CanUseGetter: false, HasJsonInclude: true }
- => @$"getter: static (obj) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")",
- _ => "getter: null"
+ => @$"static (obj) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")",
+ _ => "null"
};
- string setterNamedArg = memberMetadata switch
+ string setterValue = memberMetadata switch
{
- { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "setter: null",
+ { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null",
{ CanUseSetter: true, IsInitOnlySetter: true }
- => @$"setter: static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{ExceptionMessages.InitOnlyPropertyDeserializationNotSupported}"")",
+ => @$"static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{ExceptionMessages.InitOnlyPropertyDeserializationNotSupported}"")",
{ CanUseSetter: true } when typeGenerationSpec.IsValueType
- => $@"setter: static (obj, value) => {UnsafeTypeRef}.Unbox<{declaringTypeCompilableName}>(obj).{clrPropertyName} = value!",
+ => $@"static (obj, value) => {UnsafeTypeRef}.Unbox<{declaringTypeCompilableName}>(obj).{clrPropertyName} = value!",
{ CanUseSetter: true }
- => @$"setter: static (obj, value) => (({declaringTypeCompilableName})obj).{clrPropertyName} = value!",
+ => @$"static (obj, value) => (({declaringTypeCompilableName})obj).{clrPropertyName} = value!",
{ CanUseSetter: false, HasJsonInclude: true }
- => @$"setter: static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")",
- _ => "setter: null",
+ => @$"static (obj, value) => throw new {InvalidOperationExceptionTypeRef}(""{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.Type.Name, memberMetadata.ClrName)}"")",
+ _ => "null",
};
JsonIgnoreCondition? ignoreCondition = memberMetadata.DefaultIgnoreCondition;
string ignoreConditionNamedArg = ignoreCondition.HasValue
- ? $"ignoreCondition: {JsonIgnoreConditionTypeRef}.{ignoreCondition.Value}"
- : "ignoreCondition: null";
+ ? $"{JsonIgnoreConditionTypeRef}.{ignoreCondition.Value}"
+ : "null";
- string converterNamedArg = memberMetadata.ConverterInstantiationLogic == null
- ? "converter: null"
- : $"converter: {memberMetadata.ConverterInstantiationLogic}";
+ string converterValue = memberMetadata.ConverterInstantiationLogic == null
+ ? "null"
+ : $"{memberMetadata.ConverterInstantiationLogic}";
string memberTypeCompilableName = memberTypeMetadata.TypeRef;
+ string infoVarName = $"{InfoVarName}{i}";
+
sb.Append($@"
- {PropVarName}[{i}] = {JsonMetadataServicesTypeRef}.CreatePropertyInfo<{memberTypeCompilableName}>(
- options,
- isProperty: {ToCSharpKeyword(memberMetadata.IsProperty)},
- isPublic: {ToCSharpKeyword(memberMetadata.IsPublic)},
- isVirtual: {ToCSharpKeyword(memberMetadata.IsVirtual)},
- declaringType: typeof({memberMetadata.DeclaringTypeRef}),
- {typeTypeInfoNamedArg},
- {converterNamedArg},
- {getterNamedArg},
- {setterNamedArg},
- {ignoreConditionNamedArg},
- hasJsonInclude: {ToCSharpKeyword(memberMetadata.HasJsonInclude)},
- isExtensionData: {ToCSharpKeyword(memberMetadata.IsExtensionData)},
- numberHandling: {GetNumberHandlingAsStr(memberMetadata.NumberHandling)},
- propertyName: ""{clrPropertyName}"",
- {jsonPropertyNameNamedArg});
+ {JsonPropertyInfoValuesTypeRef}<{memberTypeCompilableName}> {infoVarName} = new {JsonPropertyInfoValuesTypeRef}<{memberTypeCompilableName}>()
+ {{
+ IsProperty = {ToCSharpKeyword(memberMetadata.IsProperty)},
+ IsPublic = {ToCSharpKeyword(memberMetadata.IsPublic)},
+ IsVirtual = {ToCSharpKeyword(memberMetadata.IsVirtual)},
+ DeclaringType = typeof({memberMetadata.DeclaringTypeRef}),
+ PropertyTypeInfo = {memberTypeFriendlyName},
+ Converter = {converterValue},
+ Getter = {getterValue},
+ Setter = {setterValue},
+ IgnoreCondition = {ignoreConditionNamedArg},
+ HasJsonInclude = {ToCSharpKeyword(memberMetadata.HasJsonInclude)},
+ IsExtensionData = {ToCSharpKeyword(memberMetadata.IsExtensionData)},
+ NumberHandling = {GetNumberHandlingAsStr(memberMetadata.NumberHandling)},
+ PropertyName = ""{clrPropertyName}"",
+ JsonPropertyName = {jsonPropertyNameValue}
+ }};
+
+ {PropVarName}[{i}] = {JsonMetadataServicesTypeRef}.CreatePropertyInfo<{memberTypeCompilableName}>(options, {infoVarName});
");
}
@@ -775,7 +795,6 @@ private string GeneratePropMetadataInitFunc(TypeGenerationSpec typeGenerationSpe
private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerationSpec)
{
const string parametersVarName = "parameters";
- const string infoVarName = "info";
ParameterGenerationSpec[] parameters = typeGenerationSpec.CtorParamGenSpecArray;
int paramCount = parameters.Length;
@@ -794,7 +813,7 @@ private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerati
ParameterInfo reflectionInfo = parameters[i].ParameterInfo;
sb.Append(@$"
- {infoVarName} = new()
+ {InfoVarName} = new()
{{
Name = ""{reflectionInfo.Name!}"",
ParameterType = typeof({reflectionInfo.ParameterType.GetCompilableName()}),
@@ -802,7 +821,7 @@ private string GenerateCtorParamMetadataInitFunc(TypeGenerationSpec typeGenerati
HasDefaultValue = {ToCSharpKeyword(reflectionInfo.HasDefaultValue)},
DefaultValue = {GetParamDefaultValueAsString(reflectionInfo.DefaultValue)}
}};
- {parametersVarName}[{i}] = {infoVarName};
+ {parametersVarName}[{i}] = {InfoVarName};
");
}
@@ -817,7 +836,7 @@ private string GenerateFastPathFuncForObject(TypeGenerationSpec typeGenSpec)
{
JsonSourceGenerationOptionsAttribute options = _currentContext.GenerationOptions;
string typeRef = typeGenSpec.TypeRef;
- string serializeMethodName = $"{typeGenSpec.TypeInfoPropertyName}{SerializeMethodNameSuffix}";
+ string serializeMethodName = $"{typeGenSpec.TypeInfoPropertyName}{SerializeHandlerPropName}";
if (!typeGenSpec.TryFilterSerializableProps(
options,
@@ -1049,7 +1068,7 @@ private string GetSerializeLogicForNonPrimitiveType(string typeInfoPropertyName,
if (serializationLogicGenerated)
{
- return $"{typeInfoPropertyName}{SerializeMethodNameSuffix}({WriterVarName}, {valueToWrite});";
+ return $"{typeInfoPropertyName}{SerializeHandlerPropName}({WriterVarName}, {valueToWrite});";
}
return $"{JsonSerializerTypeRef}.Serialize({WriterVarName}, {valueToWrite}, {typeInfoRef});";
@@ -1099,7 +1118,7 @@ private string GenerateForType(TypeGenerationSpec typeMetadata, string metadataI
{{
if (_{typeFriendlyName} == null)
{{
- {WrapWithCheckForCustomConverterIfRequired(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))}
+ {WrapWithCheckForCustomConverter(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))}
}}
return _{typeFriendlyName};
@@ -1107,23 +1126,16 @@ private string GenerateForType(TypeGenerationSpec typeMetadata, string metadataI
}}{additionalSource}";
}
- private string WrapWithCheckForCustomConverterIfRequired(string source, string typeCompilableName, string typeFriendlyName, string numberHandlingNamedArg)
- {
- if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters)
- {
- return source;
- }
-
- return @$"{JsonConverterTypeRef}? customConverter;
- if ({OptionsInstanceVariableName}.Converters.Count > 0 && (customConverter = {RuntimeCustomConverterFetchingMethodName}(typeof({typeCompilableName}))) != null)
- {{
- _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, customConverter);
- }}
- else
- {{
- {IndentSource(source, numIndentations: 1)}
- }}";
- }
+ private string WrapWithCheckForCustomConverter(string source, string typeCompilableName, string typeFriendlyName, string numberHandlingNamedArg)
+ => @$"{JsonConverterTypeRef}? customConverter;
+ if ({OptionsInstanceVariableName}.Converters.Count > 0 && (customConverter = {RuntimeCustomConverterFetchingMethodName}(typeof({typeCompilableName}))) != null)
+ {{
+ _{typeFriendlyName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeCompilableName)}({OptionsInstanceVariableName}, customConverter);
+ }}
+ else
+ {{
+ {IndentSource(source, numIndentations: 1)}
+ }}";
private string GetRootJsonContextImplementation(
bool generateGetConverterMethodForTypes,
@@ -1139,11 +1151,13 @@ private string GetRootJsonContextImplementation(
private static {contextTypeRef}? {DefaultContextBackingStaticVarName};
public static {contextTypeRef} Default => {DefaultContextBackingStaticVarName} ??= new {contextTypeRef}(new {JsonSerializerOptionsTypeRef}({DefaultOptionsStaticVarName}));
-public {contextTypeName}() : base(null, {DefaultOptionsStaticVarName})
+protected override {JsonSerializerOptionsTypeRef}? GeneratedSerializerOptions {{ get; }} = {DefaultOptionsStaticVarName};
+
+public {contextTypeName}() : base(null)
{{
}}
-public {contextTypeName}({JsonSerializerOptionsTypeRef} options) : base(options, {DefaultOptionsStaticVarName})
+public {contextTypeName}({JsonSerializerOptionsTypeRef} options) : base(options)
{{
}}
@@ -1184,11 +1198,6 @@ private string GetLogicForDefaultSerializerOptionsInit()
private string GetFetchLogicForRuntimeSpecifiedCustomConverter()
{
- if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters)
- {
- return "";
- }
-
// TODO (https://github.com/dotnet/runtime/issues/52218): use a dictionary if count > ~15.
return @$"private {JsonConverterTypeRef}? {RuntimeCustomConverterFetchingMethodName}({TypeTypeRef} type)
{{
diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
index 9ba0372893c3fd..e5cb105b39d6e4 100644
--- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
+++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
@@ -25,9 +25,12 @@ private sealed class Parser
private const string SystemTextJsonNamespace = "System.Text.Json";
private const string JsonConverterAttributeFullName = "System.Text.Json.Serialization.JsonConverterAttribute";
private const string JsonConverterFactoryFullName = "System.Text.Json.Serialization.JsonConverterFactory";
+ private const string JsonArrayFullName = "System.Text.Json.Nodes.JsonArray";
private const string JsonElementFullName = "System.Text.Json.JsonElement";
private const string JsonExtensionDataAttributeFullName = "System.Text.Json.Serialization.JsonExtensionDataAttribute";
+ private const string JsonNodeFullName = "System.Text.Json.Nodes.JsonNode";
private const string JsonObjectFullName = "System.Text.Json.Nodes.JsonObject";
+ private const string JsonValueFullName = "System.Text.Json.Nodes.JsonValue";
private const string JsonIgnoreAttributeFullName = "System.Text.Json.Serialization.JsonIgnoreAttribute";
private const string JsonIgnoreConditionFullName = "System.Text.Json.Serialization.JsonIgnoreCondition";
private const string JsonIncludeAttributeFullName = "System.Text.Json.Serialization.JsonIncludeAttribute";
@@ -80,8 +83,11 @@ private sealed class Parser
private readonly Type? _guidType;
private readonly Type? _uriType;
private readonly Type? _versionType;
+ private readonly Type? _jsonArrayType;
private readonly Type? _jsonElementType;
+ private readonly Type? _jsonNodeType;
private readonly Type? _jsonObjectType;
+ private readonly Type? _jsonValueType;
// Unsupported types
private readonly Type _typeType;
@@ -193,8 +199,11 @@ public Parser(Compilation compilation, in JsonSourceGenerationContext sourceGene
_guidType = _metadataLoadContext.Resolve(typeof(Guid));
_uriType = _metadataLoadContext.Resolve(typeof(Uri));
_versionType = _metadataLoadContext.Resolve(typeof(Version));
+ _jsonArrayType = _metadataLoadContext.Resolve(JsonArrayFullName);
_jsonElementType = _metadataLoadContext.Resolve(JsonElementFullName);
+ _jsonNodeType = _metadataLoadContext.Resolve(JsonNodeFullName);
_jsonObjectType = _metadataLoadContext.Resolve(JsonObjectFullName);
+ _jsonValueType = _metadataLoadContext.Resolve(JsonValueFullName);
// Unsupported types.
_typeType = _metadataLoadContext.Resolve(typeof(Type));
@@ -565,14 +574,6 @@ private static bool TryGetClassDeclarationList(INamedTypeSymbol typeSymbol, [Not
}
}
break;
- case nameof(JsonSourceGenerationOptionsAttribute.IgnoreRuntimeCustomConverters):
- {
- if (bool.TryParse(propertyValueStr, out bool value))
- {
- options.IgnoreRuntimeCustomConverters = value;
- }
- }
- break;
case nameof(JsonSourceGenerationOptionsAttribute.IncludeFields):
{
if (bool.TryParse(propertyValueStr, out bool value))
@@ -640,7 +641,7 @@ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGener
string? converterInstatiationLogic = null;
bool implementsIJsonOnSerialized = false;
bool implementsIJsonOnSerializing = false;
- bool hasEncounteredInitOnlyProperties = false;
+ bool hasInitOnlyProperties = false;
bool hasTypeFactoryConverter = false;
bool hasPropertyFactoryConverters = false;
@@ -972,10 +973,10 @@ void CacheMemberHelper()
_implicitlyRegisteredTypes.Add(dataExtensionPropGenSpec);
}
- if (!hasEncounteredInitOnlyProperties && spec.CanUseSetter && spec.IsInitOnlySetter)
+ if (!hasInitOnlyProperties && spec.CanUseSetter && spec.IsInitOnlySetter)
{
_sourceGenerationContext.ReportDiagnostic(Diagnostic.Create(InitOnlyPropertyDeserializationNotSupported, Location.None, new string[] { type.Name }));
- hasEncounteredInitOnlyProperties = true;
+ hasInitOnlyProperties = true;
}
if (spec.HasJsonInclude && (!spec.CanUseGetter || !spec.CanUseSetter || !spec.IsPublic))
@@ -1454,8 +1455,11 @@ private void PopulateKnownTypes()
AddTypeIfNotNull(_knownTypes, _guidType);
AddTypeIfNotNull(_knownTypes, _uriType);
AddTypeIfNotNull(_knownTypes, _versionType);
+ AddTypeIfNotNull(_knownTypes, _jsonArrayType);
AddTypeIfNotNull(_knownTypes, _jsonElementType);
+ AddTypeIfNotNull(_knownTypes, _jsonNodeType);
AddTypeIfNotNull(_knownTypes, _jsonObjectType);
+ AddTypeIfNotNull(_knownTypes, _jsonValueType);
_knownUnsupportedTypes.Add(_typeType);
_knownUnsupportedTypes.Add(_serializationInfoType);
diff --git a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs
index 02d51cdef6a48c..1b83543694361a 100644
--- a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs
+++ b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs
@@ -72,15 +72,6 @@ internal class TypeGenerationSpec
public bool HasPropertyFactoryConverters { get; private set; }
public bool HasTypeFactoryConverter { get; private set; }
- public string FastPathSerializeMethodName
- {
- get
- {
- Debug.Assert(GenerateSerializationLogic);
- return $"{TypeInfoPropertyName}Serialize";
- }
- }
-
public string? ImmutableCollectionBuilderName
{
get
diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs
index 23b632240cabe5..77d6c85b4376fe 100644
--- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs
+++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs
@@ -798,7 +798,7 @@ public abstract partial class JsonConverter
internal JsonConverter() { }
public abstract bool CanConvert(System.Type typeToConvert);
}
- [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Enum | System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple=false)]
+ [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Interface | System.AttributeTargets.Enum | System.AttributeTargets.Field | System.AttributeTargets.Property | System.AttributeTargets.Struct, AllowMultiple = false)]
public partial class JsonConverterAttribute : System.Text.Json.Serialization.JsonAttribute
{
protected JsonConverterAttribute() { }
@@ -890,7 +890,8 @@ public JsonSerializableAttribute(System.Type type) { }
}
public abstract partial class JsonSerializerContext
{
- protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions? instanceOptions, System.Text.Json.JsonSerializerOptions? defaultOptions) { }
+ protected JsonSerializerContext(System.Text.Json.JsonSerializerOptions? options) { }
+ protected abstract System.Text.Json.JsonSerializerOptions? GeneratedSerializerOptions { get; }
public System.Text.Json.JsonSerializerOptions Options { get { throw null; } }
public abstract System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(System.Type type);
}
@@ -901,11 +902,10 @@ public JsonSourceGenerationOptionsAttribute() { }
public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get { throw null; } set { } }
public bool IgnoreReadOnlyFields { get { throw null; } set { } }
public bool IgnoreReadOnlyProperties { get { throw null; } set { } }
- public bool IgnoreRuntimeCustomConverters { get { throw null; } set { } }
public bool IncludeFields { get { throw null; } set { } }
public System.Text.Json.Serialization.JsonKnownNamingPolicy PropertyNamingPolicy { get { throw null; } set { } }
public bool WriteIndented { get { throw null; } set { } }
- public JsonSourceGenerationMode GenerationMode { get { throw null; } set { } }
+ public System.Text.Json.Serialization.JsonSourceGenerationMode GenerationMode { get { throw null; } set { } }
}
[System.FlagsAttribute]
public enum JsonSourceGenerationMode
@@ -948,6 +948,15 @@ protected ReferenceResolver() { }
}
namespace System.Text.Json.Serialization.Metadata
{
+ public sealed partial class JsonCollectionInfoValues
+ {
+ public JsonCollectionInfoValues() { }
+ public System.Func? ObjectCreator { get { throw null; } init { } }
+ public System.Text.Json.Serialization.Metadata.JsonTypeInfo ElementInfo { get { throw null; } init { } }
+ public System.Text.Json.Serialization.Metadata.JsonTypeInfo? KeyInfo { get { throw null; } init { } }
+ public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } }
+ public System.Action? SerializeHandler { get { throw null; } init { } }
+ }
public static partial class JsonMetadataServices
{
public static System.Text.Json.Serialization.JsonConverter BooleanConverter { get { throw null; } }
@@ -962,8 +971,11 @@ public static partial class JsonMetadataServices
public static System.Text.Json.Serialization.JsonConverter Int16Converter { get { throw null; } }
public static System.Text.Json.Serialization.JsonConverter Int32Converter { get { throw null; } }
public static System.Text.Json.Serialization.JsonConverter Int64Converter { get { throw null; } }
+ public static System.Text.Json.Serialization.JsonConverter JsonArrayConverter { get { throw null; } }
public static System.Text.Json.Serialization.JsonConverter JsonElementConverter { get { throw null; } }
+ public static System.Text.Json.Serialization.JsonConverter JsonNodeConverter { get { throw null; } }
public static System.Text.Json.Serialization.JsonConverter JsonObjectConverter { get { throw null; } }
+ public static System.Text.Json.Serialization.JsonConverter JsonValueConverter { get { throw null; } }
public static System.Text.Json.Serialization.JsonConverter