Update source-gen APIs according to review (#59042)
authorLayomi Akinrinade <laakinri@microsoft.com>
Fri, 17 Sep 2021 04:18:23 +0000 (21:18 -0700)
committerGitHub <noreply@github.com>
Fri, 17 Sep 2021 04:18:23 +0000 (21:18 -0700)
* Update source-gen APIs according to review

* Rename fast-path func name and add src-gen/JsonNode interop support

* Address review feedback

* Disable src-gen tests in browser target OS

39 files changed:
src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs
src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs
src/libraries/System.Text.Json/ref/System.Text.Json.cs
src/libraries/System.Text.Json/src/System.Text.Json.csproj
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs [new file with mode: 0644]
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValuesOfT.cs [moved from src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValues.cs with 100% similarity]
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs [new file with mode: 0644]
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs
src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs
src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs
src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs
src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs with 65% similarity]
src/libraries/System.Text.Json/tests/Common/SampleTestData.OrderPayload.cs [moved from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/SampleTestData.OrderPayload.cs with 100% similarity]
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs [new file with mode: 0644]
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs
src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj
src/libraries/tests.proj

index 84ffc3d..45f11a4 100644 (file)
@@ -31,11 +31,6 @@ namespace System.Text.Json.Serialization
         public bool IgnoreReadOnlyProperties { get; set; }
 
         /// <summary>
-        /// Specifies whether to ignore custom converters provided at run time.
-        /// </summary>
-        public bool IgnoreRuntimeCustomConverters { get; set; }
-
-        /// <summary>
         /// Specifies whether to include fields for serialization and deserialization.
         /// </summary>
         public bool IncludeFields { get; set; }
index 131e08d..217aed6 100644 (file)
@@ -23,13 +23,18 @@ namespace System.Text.Json.SourceGeneration
             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 @@ namespace System.Text.Json.SourceGeneration
             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 @@ namespace System.Text.Json.SourceGeneration
             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 @@ namespace {@namespace}
 
                 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 @@ namespace {@namespace}
                     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 @@ namespace {@namespace}
                 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 @@ namespace {@namespace}
                         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 @@ namespace {@namespace}
     {WriterVarName}.WriteEndArray();";
 
                 return GenerateFastPathFuncForType(
-                    typeGenerationSpec.FastPathSerializeMethodName,
+                    $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}",
                     typeGenerationSpec.TypeRef,
                     serializationLogic,
                     typeGenerationSpec.CanBeNull);
@@ -599,7 +616,7 @@ namespace {@namespace}
     {WriterVarName}.WriteEndObject();";
 
                 return GenerateFastPathFuncForType(
-                    typeGenerationSpec.FastPathSerializeMethodName,
+                    $"{typeGenerationSpec.TypeInfoPropertyName}{SerializeHandlerPropName}",
                     typeGenerationSpec.TypeRef,
                     serializationLogic,
                     typeGenerationSpec.CanBeNull);
@@ -641,23 +658,23 @@ namespace {@namespace}
                 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 static {JsonPropertyInfoTypeRef}[] {propInitMethodName}({JsonSerializerC
                         ? "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 static {JsonPropertyInfoTypeRef}[] {propInitMethodName}({JsonSerializerC
             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 static {JsonParameterInfoValuesTypeRef}[] {typeGenerationSpec.TypeInfoPr
                     ParameterInfo reflectionInfo = parameters[i].ParameterInfo;
 
                     sb.Append(@$"
-    {infoVarName} = new()
+    {InfoVarName} = new()
     {{
         Name = ""{reflectionInfo.Name!}"",
         ParameterType = typeof({reflectionInfo.ParameterType.GetCompilableName()}),
@@ -802,7 +821,7 @@ private static {JsonParameterInfoValuesTypeRef}[] {typeGenerationSpec.TypeInfoPr
         HasDefaultValue = {ToCSharpKeyword(reflectionInfo.HasDefaultValue)},
         DefaultValue = {GetParamDefaultValueAsString(reflectionInfo.DefaultValue)}
     }};
-    {parametersVarName}[{i}] = {infoVarName};
+    {parametersVarName}[{i}] = {InfoVarName};
 ");
                 }
 
@@ -817,7 +836,7 @@ private static {JsonParameterInfoValuesTypeRef}[] {typeGenerationSpec.TypeInfoPr
             {
                 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 static void {serializeMethodName}({Utf8JsonWriterTypeRef} {WriterVarName
 
                 if (serializationLogicGenerated)
                 {
-                    return $"{typeInfoPropertyName}{SerializeMethodNameSuffix}({WriterVarName}, {valueToWrite});";
+                    return $"{typeInfoPropertyName}{SerializeHandlerPropName}({WriterVarName}, {valueToWrite});";
                 }
 
                 return $"{JsonSerializerTypeRef}.Serialize({WriterVarName}, {valueToWrite}, {typeInfoRef});";
@@ -1099,7 +1118,7 @@ public {typeInfoPropertyTypeRef} {typeFriendlyName}
     {{
         if (_{typeFriendlyName} == null)
         {{
-            {WrapWithCheckForCustomConverterIfRequired(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))}
+            {WrapWithCheckForCustomConverter(metadataInitSource, typeCompilableName, typeFriendlyName, GetNumberHandlingAsStr(typeMetadata.NumberHandling))}
         }}
 
         return _{typeFriendlyName};
@@ -1107,23 +1126,16 @@ public {typeInfoPropertyTypeRef} {typeFriendlyName}
 }}{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 @@ public {typeInfoPropertyTypeRef} {typeFriendlyName}
 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 static {JsonSerializerOptionsTypeRef} {DefaultOptionsStaticVarName} {{ g
 
             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)
 {{
index 9ba0372..e5cb105 100644 (file)
@@ -25,9 +25,12 @@ namespace System.Text.Json.SourceGeneration
             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 @@ namespace System.Text.Json.SourceGeneration
             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 @@ namespace System.Text.Json.SourceGeneration
                 _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 @@ namespace System.Text.Json.SourceGeneration
                                 }
                             }
                             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 @@ namespace System.Text.Json.SourceGeneration
                 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 @@ namespace System.Text.Json.SourceGeneration
                                     _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 @@ namespace System.Text.Json.SourceGeneration
                 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);
index 02d51cd..1b83543 100644 (file)
@@ -72,15 +72,6 @@ namespace System.Text.Json.SourceGeneration
         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
index 23b6322..77d6c85 100644 (file)
@@ -798,7 +798,7 @@ namespace System.Text.Json.Serialization
         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 @@ namespace System.Text.Json.Serialization
     }
     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 @@ namespace System.Text.Json.Serialization
         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 @@ namespace System.Text.Json.Serialization
 }
 namespace System.Text.Json.Serialization.Metadata
 {
+    public sealed partial class JsonCollectionInfoValues<TCollection>
+    {
+        public JsonCollectionInfoValues() { }
+        public System.Func<TCollection>? 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<System.Text.Json.Utf8JsonWriter, TCollection>? SerializeHandler { get { throw null; } init { } }
+    }
     public static partial class JsonMetadataServices
     {
         public static System.Text.Json.Serialization.JsonConverter<bool> BooleanConverter { get { throw null; } }
@@ -962,8 +971,11 @@ namespace System.Text.Json.Serialization.Metadata
         public static System.Text.Json.Serialization.JsonConverter<short> Int16Converter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<int> Int32Converter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<long> Int64Converter { get { throw null; } }
+        public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.Nodes.JsonArray> JsonArrayConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.JsonElement> JsonElementConverter { get { throw null; } }
+        public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.Nodes.JsonNode> JsonNodeConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.Nodes.JsonObject> JsonObjectConverter { get { throw null; } }
+        public static System.Text.Json.Serialization.JsonConverter<System.Text.Json.Nodes.JsonValue> JsonValueConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<object> ObjectConverter { get { throw null; } }
         [System.CLSCompliantAttribute(false)]
         public static System.Text.Json.Serialization.JsonConverter<sbyte> SByteConverter { get { throw null; } }
@@ -978,27 +990,28 @@ namespace System.Text.Json.Serialization.Metadata
         public static System.Text.Json.Serialization.JsonConverter<ulong> UInt64Converter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<System.Uri> UriConverter { get { throw null; } }
         public static System.Text.Json.Serialization.JsonConverter<System.Version> VersionConverter { get { throw null; } }
-        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TElement[]>? serializeFunc) { throw null; }
-        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentQueue<TElement> { throw null; }
-        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentStack<TElement> { throw null; }
-        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo keyInfo, System.Text.Json.Serialization.Metadata.JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Dictionary<TKey, TValue> where TKey : notnull { throw null; }
-        public static JsonTypeInfo<TCollection> CreateICollectionInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.ICollection<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, JsonTypeInfo stringInfo, JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IDictionary { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IDictionary<TKey, TValue> where TKey : notnull { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IEnumerable { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.IList { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IList<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateImmutableDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Func<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
-        public static JsonTypeInfo<TCollection> CreateImmutableEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Func<System.Collections.Generic.IEnumerable<TElement>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateIReadOnlyDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
-        public static JsonTypeInfo<TCollection> CreateISetInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.ISet<TElement> { throw null; }
-        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<System.Text.Json.Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.List<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TElement[]> collectionInfo) { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentQueue<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateConcurrentStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentStack<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.Dictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateICollectionInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.ICollection<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.IDictionary { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.IDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.IEnumerable { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIListInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.IList { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.IList<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateImmutableDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo, System.Func<System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<TKey, TValue>>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateImmutableEnumerableInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo, System.Func<System.Collections.Generic.IEnumerable<TElement>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateIReadOnlyDictionaryInfo<TCollection, TKey, TValue>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.IReadOnlyDictionary<TKey, TValue> where TKey : notnull { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateISetInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.ISet<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateListInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.List<TElement> { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<T> CreateObjectInfo<T>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonObjectInfoValues<T> objectInfo) where T : notnull { throw null; }
-        public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo<T>(System.Text.Json.JsonSerializerOptions options, bool isProperty, bool isPublic, bool isVirtual, System.Type declaringType, System.Text.Json.Serialization.Metadata.JsonTypeInfo propertyTypeInfo, System.Text.Json.Serialization.JsonConverter<T>? converter, System.Func<object, T?>? getter, System.Action<object, T?>? setter, System.Text.Json.Serialization.JsonIgnoreCondition? ignoreCondition, bool hasJsonInclude, bool isExtensionData, System.Text.Json.Serialization.JsonNumberHandling? numberHandling, string propertyName, string? jsonPropertyName) { throw null; }
-        public static JsonTypeInfo<TCollection> CreateQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Queue<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc) where TCollection : System.Collections.Generic.Stack<TElement> { throw null; }
-        public static JsonTypeInfo<TCollection> CreateStackOrQueueInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Func<TCollection>? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action<Utf8JsonWriter, TCollection>? serializeFunc, System.Action<TCollection, object?> addFunc) where TCollection : System.Collections.IEnumerable { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo<T>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues<T> propertyInfo) { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateQueueInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo, System.Action<TCollection, object?> addFunc) where TCollection : System.Collections.IEnumerable { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateQueueInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.Queue<TElement> { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateStackInfo<TCollection>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo, System.Action<TCollection, object?> addFunc) where TCollection : System.Collections.IEnumerable { throw null; }
+        public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<TCollection> CreateStackInfo<TCollection, TElement>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues<TCollection> collectionInfo) where TCollection : System.Collections.Generic.Stack<TElement> { throw null; }
         public static System.Text.Json.Serialization.Metadata.JsonTypeInfo<T> CreateValueInfo<T>(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) { throw null; }
         public static System.Text.Json.Serialization.JsonConverter<T> GetUnsupportedTypeConverter<T>() { throw null; }
         public static System.Text.Json.Serialization.JsonConverter<T> GetEnumConverter<T>(System.Text.Json.JsonSerializerOptions options) where T : struct { throw null; }
@@ -1006,15 +1019,17 @@ namespace System.Text.Json.Serialization.Metadata
     }
     public sealed partial class JsonObjectInfoValues<T>
     {
-        public System.Func<System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[]>? ConstructorParameterMetadataInitializer { get; init; }
-        public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get; init; }
-        public System.Func<T>? ObjectCreator { get; init; }
-        public System.Func<object[], T>? ObjectWithParameterizedConstructorCreator { get; init; }
-        public System.Func<System.Text.Json.Serialization.JsonSerializerContext, System.Text.Json.Serialization.Metadata.JsonPropertyInfo[]>? PropertyMetadataInitializer { get; init; }
-        public System.Action<System.Text.Json.Utf8JsonWriter, T>? SerializeHandler { get; init; }
+        public JsonObjectInfoValues() { }
+        public System.Func<System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[]>? ConstructorParameterMetadataInitializer { get { throw null; } init { } }
+        public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } }
+        public System.Func<T>? ObjectCreator { get { throw null; } init { } }
+        public System.Func<object[], T>? ObjectWithParameterizedConstructorCreator { get { throw null; } init { } }
+        public System.Func<System.Text.Json.Serialization.JsonSerializerContext, System.Text.Json.Serialization.Metadata.JsonPropertyInfo[]>? PropertyMetadataInitializer { get { throw null; } init { } }
+        public System.Action<System.Text.Json.Utf8JsonWriter, T>? SerializeHandler { get { throw null; } init { } }
     }
-    public sealed class JsonParameterInfoValues
+    public sealed partial class JsonParameterInfoValues
     {
+        public JsonParameterInfoValues() { }
         public object? DefaultValue { get { throw null; } init { } }
         public bool HasDefaultValue { get { throw null; } init { } }
         public string Name { get { throw null; } init { } }
@@ -1025,6 +1040,24 @@ namespace System.Text.Json.Serialization.Metadata
     {
         internal JsonPropertyInfo() { }
     }
+    public sealed partial class JsonPropertyInfoValues<T>
+    {
+        public JsonPropertyInfoValues() { }
+        public System.Text.Json.Serialization.JsonConverter<T>? Converter { get { throw null; } init { } }
+        public System.Type DeclaringType { get { throw null; } init { } }
+        public System.Func<object, T?>? Getter { get { throw null; } init { } }
+        public System.Text.Json.Serialization.JsonIgnoreCondition? IgnoreCondition { get { throw null; } init { } }
+        public bool HasJsonInclude { get { throw null; } init { } }
+        public bool IsExtensionData { get { throw null; } init { } }
+        public bool IsProperty { get { throw null; } init { } }
+        public bool IsPublic { get { throw null; } init { } }
+        public bool IsVirtual { get { throw null; } init { } }
+        public string? JsonPropertyName { get { throw null; } init { } }
+        public System.Text.Json.Serialization.JsonNumberHandling? NumberHandling { get { throw null; } init { } }
+        public string PropertyName { get { throw null; } init { } }
+        public System.Text.Json.Serialization.Metadata.JsonTypeInfo PropertyTypeInfo { get { throw null; } init { } }
+        public System.Action<object, T?>? Setter { get { throw null; } init { } }
+    }
     public partial class JsonTypeInfo
     {
         internal JsonTypeInfo() { }
@@ -1032,6 +1065,6 @@ namespace System.Text.Json.Serialization.Metadata
     public abstract partial class JsonTypeInfo<T> : System.Text.Json.Serialization.Metadata.JsonTypeInfo
     {
         internal JsonTypeInfo() { }
-        public System.Action<System.Text.Json.Utf8JsonWriter, T>? Serialize { get { throw null; } }
+        public System.Action<System.Text.Json.Utf8JsonWriter, T>? SerializeHandler { get { throw null; } }
     }
 }
index 2e37237..5063d0f 100644 (file)
@@ -117,13 +117,6 @@ System.Text.Json.Utf8JsonReader</PackageDescription>
     <Compile Include="System\Text\Json\Serialization\JsonSerializer.Write.Element.cs" />
     <Compile Include="System\Text\Json\Serialization\JsonSerializer.Write.Node.cs" />
     <Compile Include="System\Text\Json\Serialization\JsonSerializerContext.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\FSharpCoreReflectionProxy.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.Collections.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.Converters.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonObjectInfoValues.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfoInternalOfT.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfoOfT.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.cs" />
     <Compile Include="System\Text\Json\Serialization\ReferenceEqualsWrapper.cs" />
     <Compile Include="System\Text\Json\Serialization\ConverterStrategy.cs" />
     <Compile Include="System\Text\Json\Serialization\ConverterList.cs" />
@@ -230,14 +223,23 @@ System.Text.Json.Utf8JsonReader</PackageDescription>
     <Compile Include="System\Text\Json\Serialization\JsonSerializerOptions.cs" />
     <Compile Include="System\Text\Json\Serialization\JsonStringEnumConverter.cs" />
     <Compile Include="System\Text\Json\Serialization\JsonUnknownTypeHandling.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\FSharpCoreReflectionProxy.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\GenericMethodHolder.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonCollectionInfoValuesOfTCollection.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.Collections.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.Converters.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonMetadataServices.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonObjectInfoValuesOfT.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonParameterInfoValues.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonParameterInfo.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonParameterInfoOfT.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonPropertyInfo.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonPropertyInfoOfT.cs" />
-    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfo.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonPropertyInfoValuesOfT.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfoInternalOfT.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfoOfT.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfo.Cache.cs" />
+    <Compile Include="System\Text\Json\Serialization\Metadata\JsonTypeInfo.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\MemberAccessor.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\ParameterRef.cs" />
     <Compile Include="System\Text\Json\Serialization\Metadata\PropertyRef.cs" />
index 9bc2f3b..5ee913f 100644 (file)
@@ -8,7 +8,7 @@ namespace System.Text.Json.Serialization.Converters
 {
     /// <summary>
     /// Provides a mechanism to invoke "fast-path" serialization logic via
-    /// <see cref="JsonTypeInfo{T}.Serialize"/>. This type holds an optional
+    /// <see cref="JsonTypeInfo{T}.SerializeHandler"/>. This type holds an optional
     /// reference to an actual <see cref="JsonConverter{T}"/> for the type
     /// <typeparamref name="T"/>, to provide a fallback when the fast path cannot be used.
     /// </summary>
@@ -75,10 +75,10 @@ namespace System.Text.Json.Serialization.Converters
 
             if (!state.SupportContinuation &&
                 jsonTypeInfo is JsonTypeInfo<T> info &&
-                info.Serialize != null &&
+                info.SerializeHandler != null &&
                 info.Options._context?.CanUseSerializationLogic == true)
             {
-                info.Serialize(writer, value);
+                info.SerializeHandler(writer, value);
                 return true;
             }
 
index 8d0f7bb..5dd032c 100644 (file)
@@ -11,7 +11,7 @@ namespace System.Text.Json.Serialization.Converters
     /// Converter for JsonNode-derived types. The {T} value must be Object and not JsonNode
     /// since we allow Object-declared members\variables to deserialize as {JsonNode}.
     /// </summary>
-    internal sealed class JsonNodeConverter : JsonConverter<JsonNode?>
+    internal sealed class JsonNodeConverter : JsonConverter<JsonNode>
     {
         private static JsonNodeConverter? s_nodeConverter;
         private static JsonArrayConverter? s_arrayConverter;
index 4f10052..761798f 100644 (file)
@@ -43,8 +43,8 @@ namespace System.Text.Json
                 jsonTypeInfo is JsonTypeInfo<TValue> typedInfo &&
                 typedInfo.Options._context?.CanUseSerializationLogic == true)
             {
-                Debug.Assert(typedInfo.Serialize != null);
-                typedInfo.Serialize(writer, value);
+                Debug.Assert(typedInfo.SerializeHandler != null);
+                typedInfo.SerializeHandler(writer, value);
                 writer.Flush();
             }
             else
index 688fd91..0ce1818 100644 (file)
@@ -13,11 +13,31 @@ namespace System.Text.Json.Serialization
     public abstract partial class JsonSerializerContext
     {
         private bool? _canUseSerializationLogic;
-        private JsonSerializerOptions? _defaultOptions;
 
         internal JsonSerializerOptions? _options;
 
         /// <summary>
+        /// Gets the run time specified options of the context. If no options were passed
+        /// when instanciating the context, then a new instance is bound and returned.
+        /// </summary>
+        /// <remarks>
+        /// The instance cannot be mutated once it is bound with the context instance.
+        /// </remarks>
+        public JsonSerializerOptions Options
+        {
+            get
+            {
+                if (_options == null)
+                {
+                    _options = new JsonSerializerOptions();
+                    _options._context = this;
+                }
+
+                return _options;
+            }
+        }
+
+        /// <summary>
         /// Indicates whether pre-generated serialization logic for types in the context
         /// is compatible with the run time specified <see cref="JsonSerializerOptions"/>.
         /// </summary>
@@ -27,7 +47,7 @@ namespace System.Text.Json.Serialization
             {
                 if (!_canUseSerializationLogic.HasValue)
                 {
-                    if (_defaultOptions == null)
+                    if (GeneratedSerializerOptions == null)
                     {
                         _canUseSerializationLogic = false;
                     }
@@ -46,13 +66,13 @@ namespace System.Text.Json.Serialization
 #pragma warning restore SYSLIB0020
 
                             // Ensure options values are consistent with expected defaults.
-                            Options.DefaultIgnoreCondition == _defaultOptions.DefaultIgnoreCondition &&
-                            Options.IgnoreReadOnlyFields == _defaultOptions.IgnoreReadOnlyFields &&
-                            Options.IgnoreReadOnlyProperties == _defaultOptions.IgnoreReadOnlyProperties &&
-                            Options.IncludeFields == _defaultOptions.IncludeFields &&
-                            Options.PropertyNamingPolicy == _defaultOptions.PropertyNamingPolicy &&
-                            Options.DictionaryKeyPolicy == _defaultOptions.DictionaryKeyPolicy &&
-                            Options.WriteIndented == _defaultOptions.WriteIndented;
+                            Options.DefaultIgnoreCondition == GeneratedSerializerOptions.DefaultIgnoreCondition &&
+                            Options.IgnoreReadOnlyFields == GeneratedSerializerOptions.IgnoreReadOnlyFields &&
+                            Options.IgnoreReadOnlyProperties == GeneratedSerializerOptions.IgnoreReadOnlyProperties &&
+                            Options.IncludeFields == GeneratedSerializerOptions.IncludeFields &&
+                            Options.PropertyNamingPolicy == GeneratedSerializerOptions.PropertyNamingPolicy &&
+                            Options.DictionaryKeyPolicy == GeneratedSerializerOptions.DictionaryKeyPolicy &&
+                            Options.WriteIndented == GeneratedSerializerOptions.WriteIndented;
                     }
                 }
 
@@ -61,49 +81,30 @@ namespace System.Text.Json.Serialization
         }
 
         /// <summary>
-        /// Gets the run time specified options of the context. If no options were passed
-        /// when instanciating the context, then a new instance is bound and returned.
+        /// The default run time options for the context. Its values are defined at design-time via <see cref="JsonSourceGenerationOptionsAttribute"/>.
         /// </summary>
-        /// <remarks>
-        /// The instance cannot be mutated once it is bound with the context instance.
-        /// </remarks>
-        public JsonSerializerOptions Options
-        {
-            get
-            {
-                if (_options == null)
-                {
-                    _options = new JsonSerializerOptions();
-                    _options._context = this;
-                }
-
-                return _options;
-            }
-        }
+        protected abstract JsonSerializerOptions? GeneratedSerializerOptions { get; }
 
         /// <summary>
         /// Creates an instance of <see cref="JsonSerializerContext"/> and binds it with the indicated <see cref="JsonSerializerOptions"/>.
         /// </summary>
-        /// <param name="instanceOptions">The run time provided options for the context instance.</param>
-        /// <param name="defaultOptions">The default run time options for the context. Its values are defined at design-time via <see cref="JsonSourceGenerationOptionsAttribute"/>.</param>
+        /// <param name="options">The run time provided options for the context instance.</param>
         /// <remarks>
         /// If no instance options are passed, then no options are set until the context is bound using <see cref="JsonSerializerOptions.AddContext{TContext}"/>,
         /// or until <see cref="Options"/> is called, where a new options instance is created and bound.
         /// </remarks>
-        protected JsonSerializerContext(JsonSerializerOptions? instanceOptions, JsonSerializerOptions? defaultOptions)
+        protected JsonSerializerContext(JsonSerializerOptions? options)
         {
-            if (instanceOptions != null)
+            if (options != null)
             {
-                if (instanceOptions._context != null)
+                if (options._context != null)
                 {
                     ThrowHelper.ThrowInvalidOperationException_JsonSerializerOptionsAlreadyBoundToContext();
                 }
 
-                _options = instanceOptions;
-                instanceOptions._context = this;
+                _options = options;
+                options._context = this;
             }
-
-            _defaultOptions = defaultOptions;
         }
 
         /// <summary>
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs
new file mode 100644 (file)
index 0000000..b1fef6a
--- /dev/null
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization.Metadata
+{
+    /// <summary>
+    /// Provides serialization metadata about a collection type.
+    /// </summary>
+    /// <typeparam name="TCollection">The collection type.</typeparam>
+    public sealed class JsonCollectionInfoValues<TCollection>
+    {
+        /// <summary>
+        /// A <see cref="Func{TResult}"/> to create an instance of the collection when deserializing.
+        /// </summary>
+        public Func<TCollection>? ObjectCreator { get; init; }
+
+        /// <summary>
+        /// If a dictionary type, the <see cref="JsonTypeInfo"/> instance representing the key type.
+        /// </summary>
+        public JsonTypeInfo? KeyInfo { get; init; }
+
+        /// <summary>
+        /// A <see cref="JsonTypeInfo"/> instance representing the element type.
+        /// </summary>
+        public JsonTypeInfo ElementInfo { get; init; } = null!;
+
+        /// <summary>
+        /// The <see cref="JsonNumberHandling"/> option to apply to number collection elements.
+        /// </summary>
+        public JsonNumberHandling NumberHandling { get; init; }
+
+        /// <summary>
+        /// An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.
+        /// </summary>
+        public Action<Utf8JsonWriter, TCollection>? SerializeHandler { get; init; }
+    }
+}
index 71f48ad..4b17086 100644 (file)
@@ -11,552 +11,368 @@ namespace System.Text.Json.Serialization.Metadata
     public static partial class JsonMetadataServices
     {
         /// <summary>
-        /// Creates metadata for an array.
+        /// Creates serialization metadata for an array.
         /// </summary>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
-        public static JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(
-            JsonSerializerOptions options,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TElement[]>? serializeFunc)
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
+        public static JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(JsonSerializerOptions options, JsonCollectionInfoValues<TElement[]> collectionInfo)
             => new JsonTypeInfoInternal<TElement[]>(
                 options,
-                createObjectFunc: null,
-                () => new ArrayConverter<TElement[], TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ArrayConverter<TElement[], TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="List{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="List{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
-        /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateListInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : List<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new ListOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ListOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="Dictionary{TKey, TValue}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="Dictionary{TKey, TValue}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
         /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
-        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateDictionaryInfo<TCollection, TKey, TValue>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo keyInfo,
-            JsonTypeInfo valueInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : Dictionary<TKey, TValue>
             where TKey : notnull
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new DictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
-                keyInfo,
-                valueInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TKey),
-                typeof(TValue));
+                collectionInfo,
+                () => new DictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>());
 
 
 #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
         /// <summary>
-        /// Creates metadata for <see cref="System.Collections.Immutable.ImmutableDictionary{TKey, TValue}"/> and
+        /// Creates serialization metadata for <see cref="System.Collections.Immutable.ImmutableDictionary{TKey, TValue}"/> and
         /// types assignable to <see cref="System.Collections.Immutable.IImmutableDictionary{TKey, TValue}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
         /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
-        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
         /// <param name="createRangeFunc">A method to create an immutable dictionary instance.</param>
-        /// <returns></returns>
+        /// <returns>Serialization metadata for the given type.</returns>
 #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
         public static JsonTypeInfo<TCollection> CreateImmutableDictionaryInfo<TCollection, TKey, TValue>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo keyInfo,
-            JsonTypeInfo valueInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            JsonCollectionInfoValues<TCollection> collectionInfo,
             Func<IEnumerable<KeyValuePair<TKey, TValue>>, TCollection> createRangeFunc)
             where TCollection : IReadOnlyDictionary<TKey, TValue>
             where TKey : notnull
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
+                collectionInfo,
                 () => new ImmutableDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
-                keyInfo,
-                valueInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TKey),
-                typeof(TValue),
-                createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
+                createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IDictionary{TKey, TValue}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IDictionary{TKey, TValue}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
         /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
-        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection, TKey, TValue>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo keyInfo,
-            JsonTypeInfo valueInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IDictionary<TKey, TValue>
             where TKey : notnull
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
-                keyInfo,
-                valueInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TKey),
-                typeof(TValue));
+                collectionInfo,
+                () => new IDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IReadOnlyDictionary{TKey, TValue}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IReadOnlyDictionary{TKey, TValue}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TKey">The generic definition of the key type.</typeparam>
         /// <typeparam name="TValue">The generic definition of the value type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
-        /// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIReadOnlyDictionaryInfo<TCollection, TKey, TValue>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo keyInfo,
-            JsonTypeInfo valueInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IReadOnlyDictionary<TKey, TValue>
             where TKey : notnull
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IReadOnlyDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>(),
-                keyInfo,
-                valueInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TKey),
-                typeof(TValue));
+                collectionInfo,
+                () => new IReadOnlyDictionaryOfTKeyTValueConverter<TCollection, TKey, TValue>());
 
 #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
         /// <summary>
-        /// Creates metadata for non-dictionary immutable collection types.
+        /// Creates serialization metadata for non-dictionary immutable collection types.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
         /// <param name="createRangeFunc">A method to create an immutable dictionary instance.</param>
-        /// <returns></returns>
+        /// <returns>Serialization metadata for the given type.</returns>
 #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
         public static JsonTypeInfo<TCollection> CreateImmutableEnumerableInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            JsonCollectionInfoValues<TCollection> collectionInfo,
             Func<IEnumerable<TElement>, TCollection> createRangeFunc)
             where TCollection : IEnumerable<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
+                collectionInfo,
                 () => new ImmutableEnumerableOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement),
-                createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
+                createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc)));
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IList"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="objectInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo objectInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IList
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IListConverter<TCollection>(),
-                objectInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(object));
+                collectionInfo,
+                () => new IListConverter<TCollection>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IList{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IList{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIListInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IList<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IListOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new IListOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="ISet{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="ISet{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateISetInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : ISet<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new ISetOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ISetOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="ICollection{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="ICollection{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateICollectionInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : ICollection<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new ICollectionOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ICollectionOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="Stack{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="Stack{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateStackInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : Stack<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new StackOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new StackOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="Queue{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="Queue{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateQueueInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : Queue<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new QueueOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new QueueOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="ConcurrentStack{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="ConcurrentStack{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateConcurrentStackInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : ConcurrentStack<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new ConcurrentStackOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ConcurrentStackOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="Queue{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="Queue{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateConcurrentQueueInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : ConcurrentQueue<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new ConcurrentQueueOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new ConcurrentQueueOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IEnumerable{T}"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IEnumerable{T}"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <typeparam name="TElement">The generic definition of the element type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection, TElement>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IEnumerable<TElement>
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IEnumerableOfTConverter<TCollection, TElement>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(TElement));
+                collectionInfo,
+                () => new IEnumerableOfTConverter<TCollection, TElement>());
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IDictionary"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IDictionary"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="stringInfo">A <see cref="JsonTypeInfo"/> instance representing <see cref="string"/> instances.</param>
-        /// <param name="objectInfo">A <see cref="JsonTypeInfo"/> instance representing <see cref="object"/> instances.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIDictionaryInfo<TCollection>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo stringInfo,
-            JsonTypeInfo objectInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IDictionary
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IDictionaryConverter<TCollection>(),
-                keyInfo: stringInfo,
-                valueInfo: objectInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(string),
-                typeof(object));
+                collectionInfo,
+                () => new IDictionaryConverter<TCollection>());
+
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
+        /// <summary>
+        /// Creates serialization metadata for <see cref="System.Collections.Stack"/> types.
+        /// </summary>
+        /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
+        /// <param name="options"></param>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <param name="addFunc">A method for adding elements to the collection when using the serializer's code-paths.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+        public static JsonTypeInfo<TCollection> CreateStackInfo<TCollection>(
+            JsonSerializerOptions options,
+            JsonCollectionInfoValues<TCollection> collectionInfo,
+            Action<TCollection, object?> addFunc)
+            where TCollection : IEnumerable
+            => CreateStackOrQueueInfo(options, collectionInfo, addFunc);
 
+#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// Creates serialization metadata for <see cref="System.Collections.Queue"/> types.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
         /// <param name="addFunc">A method for adding elements to the collection when using the serializer's code-paths.</param>
-        /// <returns></returns>
-        public static JsonTypeInfo<TCollection> CreateStackOrQueueInfo<TCollection>(
+        /// <returns>Serialization metadata for the given type.</returns>
+#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved
+        public static JsonTypeInfo<TCollection> CreateQueueInfo<TCollection>(
+            JsonSerializerOptions options,
+            JsonCollectionInfoValues<TCollection> collectionInfo,
+            Action<TCollection, object?> addFunc)
+            where TCollection : IEnumerable
+            => CreateStackOrQueueInfo(options, collectionInfo, addFunc);
+
+        private static JsonTypeInfo<TCollection> CreateStackOrQueueInfo<TCollection>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc,
+            JsonCollectionInfoValues<TCollection> collectionInfo,
             Action<TCollection, object?> addFunc)
             where TCollection : IEnumerable
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
+                collectionInfo,
                 () => new StackOrQueueConverter<TCollection>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(object),
                 createObjectWithArgs: null,
                 addFunc: addFunc ?? throw new ArgumentNullException(nameof(addFunc)));
 
         /// <summary>
-        /// Creates metadata for types assignable to <see cref="IList"/>.
+        /// Creates serialization metadata for types assignable to <see cref="IList"/>.
         /// </summary>
         /// <typeparam name="TCollection">The generic definition of the type.</typeparam>
         /// <param name="options"></param>
-        /// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
-        /// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
-        /// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
-        /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
-        /// <returns></returns>
+        /// <param name="collectionInfo">Provides serialization metadata about the collection type.</param>
+        /// <returns>Serialization metadata for the given type.</returns>
         public static JsonTypeInfo<TCollection> CreateIEnumerableInfo<TCollection>(
             JsonSerializerOptions options,
-            Func<TCollection>? createObjectFunc,
-            JsonTypeInfo elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, TCollection>? serializeFunc)
+            JsonCollectionInfoValues<TCollection> collectionInfo)
             where TCollection : IEnumerable
             => new JsonTypeInfoInternal<TCollection>(
                 options,
-                createObjectFunc,
-                () => new IEnumerableConverter<TCollection>(),
-                elementInfo,
-                numberHandling,
-                serializeFunc,
-                typeof(object));
+                collectionInfo,
+                () => new IEnumerableConverter<TCollection>());
     }
 }
index 20d5b1f..5cf7292 100644 (file)
@@ -82,18 +82,36 @@ namespace System.Text.Json.Serialization.Metadata
         private static JsonConverter<long>? s_int64Converter;
 
         /// <summary>
+        /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonArray"/> values.
+        /// </summary>
+        public static JsonConverter<JsonArray> JsonArrayConverter => s_jsonArrayConverter ??= new JsonArrayConverter();
+        private static JsonConverter<JsonArray>? s_jsonArrayConverter;
+
+        /// <summary>
         /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonElement"/> values.
         /// </summary>
         public static JsonConverter<JsonElement> JsonElementConverter => s_jsonElementConverter ??= new JsonElementConverter();
         private static JsonConverter<JsonElement>? s_jsonElementConverter;
 
         /// <summary>
+        /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonNode"/> values.
+        /// </summary>
+        public static JsonConverter<JsonNode> JsonNodeConverter => s_jsonNodeConverter ??= new JsonNodeConverter();
+        private static JsonConverter<JsonNode>? s_jsonNodeConverter;
+
+        /// <summary>
         /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonObject"/> values.
         /// </summary>
         public static JsonConverter<JsonObject> JsonObjectConverter => s_jsonObjectConverter ??= new JsonObjectConverter();
         private static JsonConverter<JsonObject>? s_jsonObjectConverter;
 
         /// <summary>
+        /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="JsonArray"/> values.
+        /// </summary>
+        public static JsonConverter<JsonValue> JsonValueConverter => s_jsonValueConverter ??= new JsonValueConverter();
+        private static JsonConverter<JsonValue>? s_jsonValueConverter;
+
+        /// <summary>
         /// Returns a <see cref="JsonConverter{T}"/> instance that converts <see cref="object"/> values.
         /// </summary>
         public static JsonConverter<object?> ObjectConverter => s_objectConverter ??= new ObjectConverter();
@@ -161,7 +179,7 @@ namespace System.Text.Json.Serialization.Metadata
         /// Creates a <see cref="JsonConverter{T}"/> instance that throws <see cref="NotSupportedException"/>.
         /// </summary>
         /// <typeparam name="T">The generic definition for the type.</typeparam>
-        /// <returns></returns>
+        /// <returns>A <see cref="JsonConverter{T}"/> instance that throws <see cref="NotSupportedException"/></returns>
         public static JsonConverter<T> GetUnsupportedTypeConverter<T>()
             => new UnsupportedTypeConverter<T>();
 
@@ -170,7 +188,7 @@ namespace System.Text.Json.Serialization.Metadata
         /// </summary>
         /// <typeparam name="T">The generic definition for the enum type.</typeparam>
         /// <param name="options">The <see cref="JsonSerializerOptions"/> to use for serialization and deserialization.</param>
-        /// <returns></returns>
+        /// <returns>A <see cref="JsonConverter{T}"/> instance that converts <typeparamref name="T"/> values.</returns>
         public static JsonConverter<T> GetEnumConverter<T>(JsonSerializerOptions options) where T : struct, Enum
             => new EnumConverter<T>(EnumConverterOptions.AllowNumbers, options ?? throw new ArgumentNullException(nameof(options)));
 
@@ -179,7 +197,7 @@ namespace System.Text.Json.Serialization.Metadata
         /// </summary>
         /// <typeparam name="T">The generic definition for the underlying nullable type.</typeparam>
         /// <param name="underlyingTypeInfo">Serialization metadata for the underlying nullable type.</param>
-        /// <returns></returns>
+        /// <returns>A <see cref="JsonConverter{T}"/> instance that converts <typeparamref name="T?"/> values</returns>
         public static JsonConverter<T?> GetNullableConverter<T>(JsonTypeInfo<T> underlyingTypeInfo) where T : struct
         {
             if (underlyingTypeInfo == null)
index f7cd608..e9b0578 100644 (file)
@@ -16,58 +16,39 @@ namespace System.Text.Json.Serialization.Metadata
         /// </summary>
         /// <typeparam name="T">The type that the converter for the property returns or accepts when converting JSON data.</typeparam>
         /// <param name="options">The <see cref="JsonSerializerOptions"/> to initialize the metadata with.</param>
-        /// <param name="isProperty">Whether the CLR member is a property or field.</param>
-        /// <param name="isPublic">Whether the CLR member is public.</param>
-        /// <param name="isVirtual">Whether the CLR member is a virtual property.</param>
-        /// <param name="declaringType">The declaring type of the property or field.</param>
-        /// <param name="propertyTypeInfo">The <see cref="JsonTypeInfo"/> info for the property or field's type.</param>
-        /// <param name="converter">A <see cref="JsonConverter"/> for the property or field, specified by <see cref="JsonConverterAttribute"/>.</param>
-        /// <param name="getter">Provides a mechanism to get the property or field's value.</param>
-        /// <param name="setter">Provides a mechanism to set the property or field's value.</param>
-        /// <param name="ignoreCondition">Specifies a condition for the property to be ignored.</param>
-        /// <param name="numberHandling">If the property or field is a number, specifies how it should processed when serializing and deserializing.</param>
-        /// <param name="hasJsonInclude">Whether the property was annotated with <see cref="JsonIncludeAttribute"/>.</param>
-        /// <param name="isExtensionData">Whether the property was annotated with <see cref="JsonExtensionDataAttribute"/>.</param>
-        /// <param name="propertyName">The CLR name of the property or field.</param>
-        /// <param name="jsonPropertyName">The name to be used when processing the property or field, specified by <see cref="JsonPropertyNameAttribute"/>.</param>
+        /// <param name="propertyInfo">Provides serialization metadata about the property or field.</param>
         /// <returns>A <see cref="JsonPropertyInfo"/> instance intialized with the provided metadata.</returns>
-        public static JsonPropertyInfo CreatePropertyInfo<T>(
-            JsonSerializerOptions options,
-            bool isProperty,
-            bool isPublic,
-            bool isVirtual,
-            Type declaringType,
-            JsonTypeInfo propertyTypeInfo,
-            JsonConverter<T>? converter,
-            Func<object, T?>? getter,
-            Action<object, T?>? setter,
-            JsonIgnoreCondition? ignoreCondition,
-            bool hasJsonInclude,
-            bool isExtensionData,
-            JsonNumberHandling? numberHandling,
-            string propertyName,
-            string? jsonPropertyName)
+        public static JsonPropertyInfo CreatePropertyInfo<T>(JsonSerializerOptions options, JsonPropertyInfoValues<T> propertyInfo)
         {
             if (options == null)
             {
                 throw new ArgumentNullException(nameof(options));
             }
 
+            if (propertyInfo == null)
+            {
+                throw new ArgumentNullException(nameof(propertyInfo));
+            }
+
+            Type? declaringType = propertyInfo.DeclaringType;
             if (declaringType == null)
             {
-                throw new ArgumentNullException(nameof(declaringType));
+                throw new ArgumentException(nameof(propertyInfo.DeclaringType));
             }
 
+            JsonTypeInfo? propertyTypeInfo = propertyInfo.PropertyTypeInfo;
             if (propertyTypeInfo == null)
             {
-                throw new ArgumentNullException(nameof(propertyTypeInfo));
+                throw new ArgumentException(nameof(propertyInfo.PropertyTypeInfo));
             }
 
+            string? propertyName = propertyInfo.PropertyName;
             if (propertyName == null)
             {
-                throw new ArgumentNullException(nameof(propertyName));
+                throw new ArgumentException(nameof(propertyInfo.PropertyName));
             }
 
+            JsonConverter? converter = propertyInfo.Converter;
             if (converter == null)
             {
                 converter = propertyTypeInfo.PropertyInfoForTypeInfo.ConverterBase as JsonConverter<T>;
@@ -77,28 +58,13 @@ namespace System.Text.Json.Serialization.Metadata
                 }
             }
 
-            if (!isProperty && isVirtual)
+            if (!propertyInfo.IsProperty && propertyInfo.IsVirtual)
             {
-                throw new InvalidOperationException(SR.Format(SR.FieldCannotBeVirtual, nameof(isProperty), nameof(isVirtual)));
+                throw new InvalidOperationException(SR.Format(SR.FieldCannotBeVirtual, nameof(propertyInfo.IsProperty), nameof(propertyInfo.IsVirtual)));
             }
 
             JsonPropertyInfo<T> jsonPropertyInfo = new JsonPropertyInfo<T>();
-            jsonPropertyInfo.InitializeForSourceGen(
-                options,
-                isProperty,
-                isPublic,
-                declaringType,
-                propertyTypeInfo,
-                converter,
-                getter,
-                setter,
-                ignoreCondition,
-                hasJsonInclude,
-                isExtensionData,
-                numberHandling,
-                propertyName,
-                jsonPropertyName);
-
+            jsonPropertyInfo.InitializeForSourceGen(options, propertyInfo);
             return jsonPropertyInfo;
         }
 
@@ -122,7 +88,7 @@ namespace System.Text.Json.Serialization.Metadata
         /// <returns>A <see cref="JsonTypeInfo{T}"/> instance representing the type.</returns>
         public static JsonTypeInfo<T> CreateValueInfo<T>(JsonSerializerOptions options, JsonConverter converter)
         {
-            JsonTypeInfo<T> info = new JsonTypeInfoInternal<T>(options, ConverterStrategy.Value);
+            JsonTypeInfo<T> info = new JsonTypeInfoInternal<T>(options);
             info.PropertyInfoForTypeInfo = CreateJsonPropertyInfoForClassInfo(typeof(T), info, converter, options);
             return info;
         }
index 71363ca..f60f045 100644 (file)
@@ -116,29 +116,15 @@ namespace System.Text.Json.Serialization.Metadata
             GetPolicies(ignoreCondition, parentTypeNumberHandling);
         }
 
-        internal void InitializeForSourceGen(
-            JsonSerializerOptions options,
-            bool isProperty,
-            bool isPublic,
-            Type declaringType,
-            JsonTypeInfo typeInfo,
-            JsonConverter<T> converter,
-            Func<object, T?>? getter,
-            Action<object, T?>? setter,
-            JsonIgnoreCondition? ignoreCondition,
-            bool hasJsonInclude,
-            bool isExtensionData,
-            JsonNumberHandling? numberHandling,
-            string propertyName,
-            string? jsonPropertyName)
+        internal void InitializeForSourceGen(JsonSerializerOptions options, JsonPropertyInfoValues<T> propertyInfo)
         {
             Options = options;
-            ClrName = propertyName;
+            ClrName = propertyInfo.PropertyName;
 
             // Property name settings.
-            if (jsonPropertyName != null)
+            if (propertyInfo.JsonPropertyName != null)
             {
-                NameAsString = jsonPropertyName;
+                NameAsString = propertyInfo.JsonPropertyName;
             }
             else if (options.PropertyNamingPolicy == null)
             {
@@ -155,14 +141,27 @@ namespace System.Text.Json.Serialization.Metadata
 
             NameAsUtf8Bytes ??= Encoding.UTF8.GetBytes(NameAsString!);
             EscapedNameSection ??= JsonHelpers.GetEscapedPropertyNameSection(NameAsUtf8Bytes, Options.Encoder);
-
-            SrcGen_IsPublic = isPublic;
-            SrcGen_HasJsonInclude = hasJsonInclude;
-            SrcGen_IsExtensionData = isExtensionData;
+            SrcGen_IsPublic = propertyInfo.IsPublic;
+            SrcGen_HasJsonInclude = propertyInfo.HasJsonInclude;
+            SrcGen_IsExtensionData = propertyInfo.IsExtensionData;
             DeclaredPropertyType = typeof(T);
+
+            JsonTypeInfo propertyTypeInfo = propertyInfo.PropertyTypeInfo;
+            Type declaringType = propertyInfo.DeclaringType;
+
+            JsonConverter? converter = propertyInfo.Converter;
+            if (converter == null)
+            {
+                converter = propertyTypeInfo.PropertyInfoForTypeInfo.ConverterBase as JsonConverter<T>;
+                if (converter == null)
+                {
+                    throw new InvalidOperationException(SR.Format(SR.ConverterForPropertyMustBeValid, declaringType, ClrName, typeof(T)));
+                }
+            }
+
             ConverterBase = converter;
 
-            if (ignoreCondition == JsonIgnoreCondition.Always)
+            if (propertyInfo.IgnoreCondition == JsonIgnoreCondition.Always)
             {
                 IsIgnored = true;
                 Debug.Assert(!ShouldSerialize);
@@ -170,23 +169,23 @@ namespace System.Text.Json.Serialization.Metadata
             }
             else
             {
-                Get = getter!;
-                Set = setter;
+                Get = propertyInfo.Getter!;
+                Set = propertyInfo.Setter;
                 HasGetter = Get != null;
                 HasSetter = Set != null;
-                RuntimeTypeInfo = typeInfo;
+                RuntimeTypeInfo = propertyTypeInfo;
                 DeclaringType = declaringType;
-                IgnoreCondition = ignoreCondition;
-                MemberType = isProperty ? MemberTypes.Property : MemberTypes.Field;
+                IgnoreCondition = propertyInfo.IgnoreCondition;
+                MemberType = propertyInfo.IsProperty ? MemberTypes.Property : MemberTypes.Field;
 
-                _converterIsExternalAndPolymorphic = !converter.IsInternalConverter && DeclaredPropertyType != converter.TypeToConvert;
+                _converterIsExternalAndPolymorphic = !ConverterBase.IsInternalConverter && DeclaredPropertyType != ConverterBase.TypeToConvert;
                 PropertyTypeCanBeNull = typeof(T).CanBeNull();
-                _propertyTypeEqualsTypeToConvert = converter.TypeToConvert == typeof(T);
+                _propertyTypeEqualsTypeToConvert = ConverterBase.TypeToConvert == typeof(T);
                 ConverterStrategy = Converter!.ConverterStrategy;
                 RuntimePropertyType = DeclaredPropertyType;
                 DetermineIgnoreCondition(IgnoreCondition);
                 // TODO: this method needs to also take the number handling option for the declaring type.
-                DetermineNumberHandlingForProperty(numberHandling, declaringTypeNumberHandling: null);
+                DetermineNumberHandlingForProperty(propertyInfo.NumberHandling, declaringTypeNumberHandling: null);
                 DetermineSerializationCapabilities(IgnoreCondition);
             }
         }
diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs
new file mode 100644 (file)
index 0000000..ed7fffe
--- /dev/null
@@ -0,0 +1,82 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization.Metadata
+{
+    /// <summary>
+    /// Provides serialization metadata about a property or field.
+    /// </summary>
+    /// <typeparam name="T">The type to convert of the <see cref="JsonConverter{T}"/> for the property.</typeparam>
+    public sealed class JsonPropertyInfoValues<T>
+    {
+        /// <summary>
+        /// If <see langword="true"/>, indicates that the member is a property, otherwise indicates the member is a field.
+        /// </summary>
+        public bool IsProperty { get; init; }
+
+        /// <summary>
+        /// Whether the property or field is public.
+        /// </summary>
+        public bool IsPublic { get; init; }
+
+        /// <summary>
+        /// Whether the property or field is a virtual property.
+        /// </summary>
+        public bool IsVirtual { get; init; }
+
+        /// <summary>
+        /// The declaring type of the property or field.
+        /// </summary>
+        public Type DeclaringType { get; init; } = null!;
+
+        /// <summary>
+        /// The <see cref="JsonTypeInfo"/> info for the property or field's type.
+        /// </summary>
+        public JsonTypeInfo PropertyTypeInfo { get; init; } = null!;
+
+        /// <summary>
+        /// A <see cref="JsonConverter"/> for the property or field, specified by <see cref="JsonConverterAttribute"/>.
+        /// </summary>
+        public JsonConverter<T>? Converter { get; init; }
+
+        /// <summary>
+        /// Provides a mechanism to get the property or field's value.
+        /// </summary>
+        public Func<object, T?>? Getter { get; init; }
+
+        /// <summary>
+        /// Provides a mechanism to set the property or field's value.
+        /// </summary>
+        public Action<object, T?>? Setter { get; init; }
+
+        /// <summary>
+        /// Specifies a condition for the member to be ignored.
+        /// </summary>
+        public JsonIgnoreCondition? IgnoreCondition { get; init; }
+
+        /// <summary>
+        /// Whether the property was annotated with <see cref="JsonIncludeAttribute"/>.
+        /// </summary>
+        public bool HasJsonInclude { get; init; }
+
+        /// <summary>
+        /// Whether the property was annotated with <see cref="JsonExtensionDataAttribute"/>.
+        /// </summary>
+        public bool IsExtensionData { get; init; }
+
+        /// <summary>
+        /// If the property or field is a number, specifies how it should processed when serializing and deserializing.
+        /// </summary>
+        public JsonNumberHandling? NumberHandling { get; init; }
+
+        /// <summary>
+        /// The name of the property or field.
+        /// </summary>
+        public string PropertyName { get; init; } = null!;
+
+        /// <summary>
+        /// The name to be used when processing the property or field, specified by <see cref="JsonPropertyNameAttribute"/>.
+        /// </summary>
+        public string? JsonPropertyName { get; init; }
+    }
+}
index cafba2f..55dd814 100644 (file)
@@ -147,7 +147,7 @@ namespace System.Text.Json.Serialization.Metadata
             Debug.Assert(false, "This constructor should not be called.");
         }
 
-        internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy)
+        internal JsonTypeInfo(Type type, JsonSerializerOptions options, bool dummy)
         {
             Type = type;
             Options = options ?? throw new ArgumentNullException(nameof(options));
index e7e5dc7..552b496 100644 (file)
@@ -1,7 +1,6 @@
 ï»¿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System.Collections.Generic;
 using System.Text.Json.Serialization.Converters;
 
 namespace System.Text.Json.Serialization.Metadata
@@ -13,17 +12,17 @@ namespace System.Text.Json.Serialization.Metadata
     internal sealed class JsonTypeInfoInternal<T> : JsonTypeInfo<T>
     {
         /// <summary>
-        /// Creates serialization metadata given JsonSerializerOptions and a ConverterStrategy.
+        /// Creates serialization metadata for a type using a simple converter.
         /// </summary>
-        public JsonTypeInfoInternal(JsonSerializerOptions options, ConverterStrategy converterStrategy)
-            : base(typeof(T), options, converterStrategy)
+        public JsonTypeInfoInternal(JsonSerializerOptions options)
+            : base(typeof(T), options)
         {
         }
 
         /// <summary>
         /// Creates serialization metadata for an object.
         /// </summary>
-        public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues<T> objectInfo) : base(typeof(T), options, ConverterStrategy.Object)
+        public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues<T> objectInfo) : base(typeof(T), options)
         {
 #pragma warning disable CS8714
             // The type cannot be used as type parameter in the generic type or method.
@@ -46,66 +45,40 @@ namespace System.Text.Json.Serialization.Metadata
 #pragma warning restore CS8714
 
             PropInitFunc = objectInfo.PropertyMetadataInitializer;
-            Serialize = objectInfo.SerializeHandler;
+            SerializeHandler = objectInfo.SerializeHandler;
             PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, Options);
             NumberHandling = objectInfo.NumberHandling;
         }
 
         /// <summary>
-        /// Creates serialization metadata for a <see cref="ConverterStrategy.Enumerable"/>.
+        /// Creates serialization metadata for a collection.
         /// </summary>
         public JsonTypeInfoInternal(
             JsonSerializerOptions options,
-            Func<T>? createObjectFunc,
+            JsonCollectionInfoValues<T> collectionInfo,
             Func<JsonConverter<T>> converterCreator,
-            JsonTypeInfo? elementInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, T>? serializeFunc,
-            Type elementType,
             object? createObjectWithArgs = null,
             object? addFunc = null)
-            : base(typeof(T), options, ConverterStrategy.Enumerable)
+            : base(typeof(T), options)
         {
-            JsonConverter<T> converter = new JsonMetadataServicesConverter<T>(converterCreator, ConverterStrategy.Enumerable);
-
-            ElementType = converter.ElementType;
-            ElementTypeInfo = elementInfo ?? throw new ArgumentNullException(nameof(elementInfo));
-            NumberHandling = numberHandling;
-            PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options);
-            Serialize = serializeFunc;
-            CreateObjectWithArgs = createObjectWithArgs;
-            AddMethodDelegate = addFunc;
-            SetCreateObjectFunc(createObjectFunc);
-        }
+            if (collectionInfo == null)
+            {
+                throw new ArgumentNullException(nameof(collectionInfo));
+            }
 
-        /// <summary>
-        /// Creates serialization metadata for a <see cref="ConverterStrategy.Dictionary"/>.
-        /// </summary>
-        public JsonTypeInfoInternal(
-            JsonSerializerOptions options,
-            Func<T>? createObjectFunc,
-            Func<JsonConverter<T>> converterCreator,
-            JsonTypeInfo? keyInfo,
-            JsonTypeInfo? valueInfo,
-            JsonNumberHandling numberHandling,
-            Action<Utf8JsonWriter, T>? serializeFunc,
-            Type keyType,
-            Type elementType,
-            object? createObjectWithArgs = null)
-            : base(typeof(T), options, ConverterStrategy.Dictionary)
-        {
-            JsonConverter<T> converter = new JsonMetadataServicesConverter<T>(converterCreator, ConverterStrategy.Dictionary);
+            ConverterStrategy strategy = collectionInfo.KeyInfo == null ? ConverterStrategy.Enumerable : ConverterStrategy.Dictionary;
+            JsonConverter<T> converter = new JsonMetadataServicesConverter<T>(converterCreator, strategy);
 
             KeyType = converter.KeyType;
             ElementType = converter.ElementType;
-            KeyTypeInfo = keyInfo ?? throw new ArgumentNullException(nameof(keyInfo));
-            ElementType = converter.ElementType;
-            ElementTypeInfo = valueInfo ?? throw new ArgumentNullException(nameof(valueInfo));
-            NumberHandling = numberHandling;
+            KeyTypeInfo = collectionInfo.KeyInfo;
+            ElementTypeInfo = collectionInfo.ElementInfo ?? throw new ArgumentNullException(nameof(collectionInfo.ElementInfo));
+            NumberHandling = collectionInfo.NumberHandling;
             PropertyInfoForTypeInfo = JsonMetadataServices.CreateJsonPropertyInfoForClassInfo(typeof(T), this, converter, options);
-            Serialize = serializeFunc;
+            SerializeHandler = collectionInfo.SerializeHandler;
             CreateObjectWithArgs = createObjectWithArgs;
-            SetCreateObjectFunc(createObjectFunc);
+            AddMethodDelegate = addFunc;
+            SetCreateObjectFunc(collectionInfo.ObjectCreator);
         }
 
         private void SetCreateObjectFunc(Func<T>? createObjectFunc)
index 337fd7c..e09f840 100644 (file)
@@ -15,8 +15,8 @@ namespace System.Text.Json.Serialization.Metadata
     {
         private Action<Utf8JsonWriter, T>? _serialize;
 
-        internal JsonTypeInfo(Type type, JsonSerializerOptions options, ConverterStrategy converterStrategy) :
-            base(type, options, converterStrategy)
+        internal JsonTypeInfo(Type type, JsonSerializerOptions options) :
+            base(type, options, dummy: false)
         { }
 
         internal JsonTypeInfo()
@@ -25,10 +25,11 @@ namespace System.Text.Json.Serialization.Metadata
         }
 
         /// <summary>
-        /// A method that serializes an instance of <typeparamref name="T"/> using
+        /// Serializes an instance of <typeparamref name="T"/> using
         /// <see cref="JsonSourceGenerationOptionsAttribute"/> values specified at design time.
         /// </summary>
-        public Action<Utf8JsonWriter, T>? Serialize
+        /// <remarks>The writer is not flushed after writing.</remarks>
+        public Action<Utf8JsonWriter, T>? SerializeHandler
         {
             get
             {
index 04b3b14..44a0f05 100644 (file)
@@ -666,23 +666,26 @@ namespace System.Text.Json.Serialization.Tests
 
         public class CustomInt32ConverterSerializerContext : JsonSerializerContext
         {
-            public CustomInt32ConverterSerializerContext() : base(null, null) { }
+            public CustomInt32ConverterSerializerContext() : base(null) { }
             public override JsonTypeInfo? GetTypeInfo(Type _) => throw new NotImplementedException();
 
             public JsonTypeInfo<Dictionary<int, string>> DictionaryInt32String => _dictionaryInt32String ??= CreateDictionaryConverter();
             private JsonTypeInfo<Dictionary<int, string>>? _dictionaryInt32String;
 
+            protected override JsonSerializerOptions? GeneratedSerializerOptions => null;
+
             private JsonTypeInfo<Dictionary<int, string>> CreateDictionaryConverter()
             {
                 JsonTypeInfo<int> keyInfo = JsonMetadataServices.CreateValueInfo<int>(Options, new ConverterForInt32());
                 JsonTypeInfo<string> valueInfo = JsonMetadataServices.CreateValueInfo<string>(Options, JsonMetadataServices.StringConverter);
-                return JsonMetadataServices.CreateDictionaryInfo<Dictionary<int, string>, int, string>(
-                    Options,
-                    createObjectFunc: () => new(),
-                    keyInfo, valueInfo,
-                    numberHandling: default,
-                    serializeFunc: null
-                );
+                JsonCollectionInfoValues<Dictionary<int, string>> info = new()
+                {
+                    ObjectCreator = () => new(),
+                    KeyInfo = keyInfo,
+                    ElementInfo = valueInfo,
+                };
+
+                return JsonMetadataServices.CreateDictionaryInfo<Dictionary<int, string>, int, string>(Options, info);
             }
         }
 
index 528ac29..1f1c05c 100644 (file)
@@ -3,6 +3,8 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Text.Json.Serialization.Tests;
+using System.Text.Json.Serialization.Tests.Schemas.OrderPayload;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Xunit;
@@ -84,5 +86,187 @@ namespace System.Text.Json
 
         public static string StripWhitespace(this string value)
             => s_stripWhitespace.Replace(value, string.Empty);
+
+        internal static List<Order> PopulateLargeObject(int size)
+        {
+            List<Order> orders = new List<Order>(size);
+            for (int i = 0; i < size; i++)
+            {
+                Order order = new Order
+                {
+                    OrderNumber = i,
+                    Customer = new User
+                    {
+                        UserId = "222ffbbb888kkk",
+                        Name = "John Doe",
+                        Username = "johndoe",
+                        CreatedAt = new DateTime(),
+                        ImageId = string.Empty,
+                        UserType = UserType.Customer,
+                        UpdatedAt = new DateTime(),
+                        TwitterId = string.Empty,
+                        FacebookId = "9988998877662222111",
+                        SubscriptionType = 2,
+                        IsNew = true,
+                        IsEmployee = false
+                    },
+                    ShippingInfo = new List<ShippingInfo>
+                    {
+                        new ShippingInfo()
+                        {
+                            OrderNumber = i,
+                            Employee = new User
+                            {
+                                UserId = "222ffbbb888" + i,
+                                Name = "Shipping Coordinator",
+                                Username = "coordinator" + i,
+                                CreatedAt = new DateTime(),
+                                ImageId = string.Empty,
+                                UserType = UserType.Employee,
+                                UpdatedAt = new DateTime(),
+                                TwitterId = string.Empty,
+                                SubscriptionType = 0,
+                                IsEmployee = true
+                            },
+                            CarrierId = "TTT123999MMM",
+                            ShippingType = "Ground",
+                            EstimatedDelivery = new DateTime(),
+                            Tracking = new Uri("http://TestShipCompany.test/track/123" + i),
+                            CarrierName = "TestShipCompany",
+                            HandlingInstruction = "Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats",
+                            CurrentStatus = "Out for delivery",
+                            IsDangerous = false
+                        }
+                    },
+                    OneTime = true,
+                    Cancelled = false,
+                    IsGift = i % 2 == 0,
+                    IsGPickUp = i % 5 == 0,
+                    ShippingAddress = new Address()
+                    {
+                        City = "Redmond"
+                    },
+                    PickupAddress = new Address
+                    {
+                        City = "Bellevue"
+                    },
+                    Coupon = SampleEnumInt64.Max,
+                    UserInteractions = new List<Comment>
+                    {
+                        new Comment
+                        {
+                            Id = 200 + i,
+                            OrderNumber = i,
+                            Customer = new User
+                            {
+                                UserId = "222ffbbb888kkk",
+                                Name = "John Doe",
+                                Username = "johndoe",
+                                CreatedAt = new DateTime(),
+                                ImageId = string.Empty,
+                                UserType = UserType.Customer,
+                                UpdatedAt = new DateTime(),
+                                TwitterId = "twitterId" + i,
+                                FacebookId = "9988998877662222111",
+                                SubscriptionType = 2,
+                                IsNew = true,
+                                IsEmployee = false
+                            },
+                            Title = "Green Field",
+                            Message = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to",
+                            Responses = new List<Comment>()
+                        }
+                    },
+                    Created = new DateTime(2019, 11, 10),
+                    Confirmed = new DateTime(2019, 11, 11),
+                    ShippingDate = new DateTime(2019, 11, 12),
+                    EstimatedDelivery = new DateTime(2019, 11, 15),
+                    ReviewedBy = new User()
+                    {
+                        UserId = "222ffbbb888" + i,
+                        Name = "Shipping Coordinator",
+                        Username = "coordinator" + i,
+                        CreatedAt = new DateTime(),
+                        ImageId = string.Empty,
+                        UserType = UserType.Employee,
+                        UpdatedAt = new DateTime(),
+                        TwitterId = string.Empty,
+                        SubscriptionType = 0,
+                        IsEmployee = true
+                    }
+                };
+                List<Product> products = new List<Product>();
+                for (int j = 0; j < i % 4; j++)
+                {
+                    Product product = new Product()
+                    {
+                        ProductId = Guid.NewGuid(),
+                        Name = "Surface Pro",
+                        SKU = "LL123" + j,
+                        Brand = new TestClassWithInitializedProperties(),
+                        ProductCategory = new SimpleTestClassWithNonGenericCollectionWrappers(),
+                        Description = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to",
+                        Created = new DateTime(2000, 10, 12),
+                        Title = "Surface Pro 6 for Business - 512GB",
+                        Price = new Price(),
+                        BestChoice = true,
+                        AverageStars = 4.8f,
+                        Featured = true,
+                        ProductRestrictions = new TestClassWithInitializedProperties(),
+                        SalesInfo = new SimpleTestClassWithGenericCollectionWrappers(),
+                        Origin = SampleEnum.One,
+                        Manufacturer = new BasicCompany(),
+                        Fragile = true,
+                        DetailsUrl = new Uri("http://dotnet.test/link/entries/entry/1"),
+                        NetWeight = 2.7m,
+                        GrossWeight = 3.3m,
+                        Length = i,
+                        Height = i + 1,
+                        Width = i + 2,
+                        FeaturedImage = new FeaturedImage(),
+                        PreviewImage = new PreviewImage(),
+                        KeyWords = new List<string> { "surface", "pro", "laptop" },
+                        RelatedImages = new List<Image>(),
+                        RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"),
+                        GuaranteeStartsAt = new DateTime(),
+                        GuaranteeEndsAt = new DateTime(),
+                        IsActive = true,
+                        RelatedProducts = new List<Product>()
+                    };
+                    product.SalesInfo.Initialize();
+                    List<Review> reviews = new List<Review>();
+                    for (int k = 0; k < i % 3; k++)
+                    {
+
+                        Review review = new Review
+                        {
+                            Customer = new User
+                            {
+                                UserId = "333344445555",
+                                Name = "Customer" + i + k,
+                                Username = "cust" + i + k,
+                                CreatedAt = new DateTime(),
+                                ImageId = string.Empty,
+                                UserType = UserType.Customer,
+                                SubscriptionType = k
+                            },
+                            ProductSku = product.SKU,
+                            CustomerName = "Customer" + i + k,
+                            Stars = j + k,
+                            Title = $"Title {i}{j}{k}",
+                            Comment = "",
+                            Images = new List<Uri> { new Uri($"http://dotnet.test/link/images/image/{k}"), new Uri($"http://dotnet.test/link/images/image/{j}") },
+                            ReviewId = i + j + k
+                        };
+                        reviews.Add(review);
+                    }
+                    product.Reviews = reviews;
+                    products.Add(product);
+                }
+                order.Products = products;
+                orders.Add(order);
+            }
+            return orders;
+        }
     }
 }
@@ -2,20 +2,24 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using System.Collections.Generic;
+using System.Text.Json.Nodes;
 using System.Text.Json.Serialization.Tests.Schemas.OrderPayload;
+using System.Threading.Tasks;
 using Xunit;
 
-namespace System.Text.Json.Nodes.Tests
+namespace System.Text.Json.Serialization.Tests
 {
-    public static class SerializerInteropTests
+    public abstract class NodeInteropTests : SerializerTests
     {
+        public NodeInteropTests(JsonSerializerWrapperForString serializerWrapper) : base(serializerWrapper) { }
+
         [Fact]
-        public static void CompareResultsAgainstSerializer()
+        public async Task CompareResultsAgainstSerializer()
         {
-            List<Order> obj = Serialization.Tests.StreamTests.PopulateLargeObject(2);
-            string expected = JsonSerializer.Serialize(obj);
+            List<Order> obj = JsonTestHelper.PopulateLargeObject(2);
+            string expected = await JsonSerializerWrapperForString.SerializeWrapper(obj);
 
-            JsonArray jArray = JsonSerializer.Deserialize<JsonArray>(expected);
+            JsonArray jArray = await JsonSerializerWrapperForString.DeserializeWrapper<JsonArray>(expected);
             string actual = jArray.ToJsonString();
             Assert.Equal(expected, actual);
 
@@ -24,7 +28,7 @@ namespace System.Text.Json.Nodes.Tests
             Assert.Equal(expected, actual);
         }
 
-        private class Poco
+        public class Poco
         {
             public string MyString { get; set; }
             public JsonNode Node { get; set; }
@@ -35,7 +39,7 @@ namespace System.Text.Json.Nodes.Tests
         }
 
         [Fact]
-        public static void NodesAsPocoProperties()
+        public async Task NodesAsPocoProperties()
         {
             const string Expected = "{\"MyString\":null,\"Node\":42,\"Array\":[43],\"Value\":44,\"IntValue\":45,\"Object\":{\"Property\":46}}";
 
@@ -51,10 +55,10 @@ namespace System.Text.Json.Nodes.Tests
                 }
             };
 
-            string json = JsonSerializer.Serialize(poco);
+            string json = await JsonSerializerWrapperForString.SerializeWrapper(poco);
             Assert.Equal(Expected, json);
 
-            poco = JsonSerializer.Deserialize<Poco>(json);
+            poco = await JsonSerializerWrapperForString.DeserializeWrapper<Poco>(json);
             Assert.Equal(42, (int)poco.Node);
             Assert.Equal(43, (int)poco.Array[0]);
             Assert.Equal(44, (int)poco.Value);
index f78c0a4..682323f 100644 (file)
@@ -57,14 +57,16 @@ namespace System.Text.Json.SourceGeneration.Tests
         private static JsonContext s_defaultContext;
         public static JsonContext Default => s_defaultContext ??= new JsonContext(new JsonSerializerOptions(s_defaultOptions));
 
-        public JsonContext() : base(null, s_defaultOptions)
+        public JsonContext() : base(null)
         {
         }
 
-        public JsonContext(JsonSerializerOptions options) : base(options, s_defaultOptions)
+        public JsonContext(JsonSerializerOptions options) : base(options)
         {
         }
 
+        protected override JsonSerializerOptions? GeneratedSerializerOptions => s_defaultOptions;
+
         public override JsonTypeInfo GetTypeInfo(global::System.Type type)
         {
             if (type == typeof(JsonMessage))
index a74dd32..e204e89 100644 (file)
@@ -50,28 +50,28 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.NotNull(MetadataAndSerializationContext.Default.Location.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.NumberTypes.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.RepeatedLocation.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.ActiveOrUpcomingEvent.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.IndexViewModel.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.EmptyPoco.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTemps.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyType.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyType2.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithCallbacks.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithPropertyOrdering.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyIntermediateType.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedClass.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(MetadataAndSerializationContext.Default.ObjectArray.Serialize);
-            Assert.Null(MetadataAndSerializationContext.Default.SampleEnum.Serialize);
-            Assert.Null(MetadataAndSerializationContext.Default.String.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithEnumAndNullable.Serialize);
+            Assert.NotNull(MetadataAndSerializationContext.Default.Location.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.NumberTypes.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.ActiveOrUpcomingEvent.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.IndexViewModel.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.EmptyPoco.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTemps.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyType.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyType2.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithCallbacks.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyTypeWithPropertyOrdering.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedClass.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(MetadataAndSerializationContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(MetadataAndSerializationContext.Default.SampleEnum.SerializeHandler);
+            Assert.Null(MetadataAndSerializationContext.Default.String.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithEnumAndNullable.SerializeHandler);
             Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverter);
             Assert.NotNull(MetadataAndSerializationContext.Default.StructWithCustomConverter);
             Assert.NotNull(MetadataAndSerializationContext.Default.ClassWithCustomConverterFactory);
index d9fb766..3b9a837 100644 (file)
@@ -49,36 +49,36 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.Location.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.RepeatedLocation.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.NumberTypes.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.IndexViewModel.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.EmptyPoco.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTemps.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType2.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyIntermediateType.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedClass.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.SampleEnum.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverter.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverter.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterPropertyFactory.Serialize);
-            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterPropertyFactory.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MetadataWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MetadataWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.Serialize);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.Location.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.NumberTypes.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.IndexViewModel.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.EmptyPoco.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTemps.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyType2.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.String.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverter.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverter.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Null(MetadataWithPerTypeAttributeContext.Default.StructWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MetadataWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MetadataWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler);
         }
     }
 
@@ -147,38 +147,38 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.Null(MetadataContext.Default.Location.Serialize);
-            Assert.Null(MetadataContext.Default.RepeatedLocation.Serialize);
-            Assert.Null(MetadataContext.Default.NumberTypes.Serialize);
-            Assert.Null(MetadataContext.Default.ActiveOrUpcomingEvent.Serialize);
-            Assert.Null(MetadataContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.Null(MetadataContext.Default.IndexViewModel.Serialize);
-            Assert.Null(MetadataContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.Null(MetadataContext.Default.EmptyPoco.Serialize);
-            Assert.Null(MetadataContext.Default.HighLowTemps.Serialize);
-            Assert.Null(MetadataContext.Default.MyType.Serialize);
-            Assert.Null(MetadataContext.Default.MyType2.Serialize);
-            Assert.Null(MetadataContext.Default.MyTypeWithCallbacks.Serialize);
-            Assert.Null(MetadataContext.Default.MyTypeWithPropertyOrdering.Serialize);
-            Assert.Null(MetadataContext.Default.MyIntermediateType.Serialize);
-            Assert.Null(MetadataContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.Null(MetadataContext.Default.MyNestedClass.Serialize);
-            Assert.Null(MetadataContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(MetadataContext.Default.ObjectArray.Serialize);
-            Assert.Null(MetadataContext.Default.SampleEnum.Serialize);
-            Assert.Null(MetadataContext.Default.String.Serialize);
-            Assert.Null(MetadataContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.Null(MetadataContext.Default.ClassWithEnumAndNullable.Serialize);
-            Assert.Null(MetadataContext.Default.ClassWithCustomConverter.Serialize);
-            Assert.Null(MetadataContext.Default.StructWithCustomConverter.Serialize);
-            Assert.Null(MetadataContext.Default.ClassWithCustomConverterFactory.Serialize);
-            Assert.Null(MetadataContext.Default.StructWithCustomConverterFactory.Serialize);
-            Assert.Null(MetadataContext.Default.ClassWithCustomConverterProperty.Serialize);
-            Assert.Null(MetadataContext.Default.StructWithCustomConverterProperty.Serialize);
-            Assert.Null(MetadataContext.Default.ClassWithCustomConverterPropertyFactory.Serialize);
-            Assert.Null(MetadataContext.Default.StructWithCustomConverterPropertyFactory.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MetadataContext.Default.ClassWithBadCustomConverter.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MetadataContext.Default.StructWithBadCustomConverter.Serialize);
+            Assert.Null(MetadataContext.Default.Location.SerializeHandler);
+            Assert.Null(MetadataContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.Null(MetadataContext.Default.NumberTypes.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ActiveOrUpcomingEvent.SerializeHandler);
+            Assert.Null(MetadataContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.Null(MetadataContext.Default.IndexViewModel.SerializeHandler);
+            Assert.Null(MetadataContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.Null(MetadataContext.Default.EmptyPoco.SerializeHandler);
+            Assert.Null(MetadataContext.Default.HighLowTemps.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyType.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyType2.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyTypeWithCallbacks.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyTypeWithPropertyOrdering.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.Null(MetadataContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyNestedClass.SerializeHandler);
+            Assert.Null(MetadataContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(MetadataContext.Default.SampleEnum.SerializeHandler);
+            Assert.Null(MetadataContext.Default.String.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ClassWithEnumAndNullable.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ClassWithCustomConverter.SerializeHandler);
+            Assert.Null(MetadataContext.Default.StructWithCustomConverter.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ClassWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MetadataContext.Default.StructWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ClassWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MetadataContext.Default.StructWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MetadataContext.Default.ClassWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Null(MetadataContext.Default.StructWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MetadataContext.Default.ClassWithBadCustomConverter.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MetadataContext.Default.StructWithBadCustomConverter.SerializeHandler);
         }
 
         [Fact]
index 82b8288..ede23fc 100644 (file)
@@ -50,37 +50,37 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.Null(MixedModeContext.Default.Location.Serialize);
-            Assert.NotNull(MixedModeContext.Default.RepeatedLocation.Serialize);
-            Assert.Null(MixedModeContext.Default.NumberTypes.Serialize);
-            Assert.NotNull(MixedModeContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.Null(MixedModeContext.Default.IndexViewModel.Serialize);
-            Assert.Null(MixedModeContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(MixedModeContext.Default.EmptyPoco.Serialize);
-            Assert.NotNull(MixedModeContext.Default.HighLowTemps.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyType.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyType2.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyTypeWithCallbacks.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyTypeWithPropertyOrdering.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyIntermediateType.Serialize);
-            Assert.Null(MixedModeContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyNestedClass.Serialize);
-            Assert.NotNull(MixedModeContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(MixedModeContext.Default.ObjectArray.Serialize);
-            Assert.Null(MixedModeContext.Default.SampleEnum.Serialize);
-            Assert.Null(MixedModeContext.Default.String.Serialize);
-            Assert.NotNull(MixedModeContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.NotNull(MixedModeContext.Default.ClassWithEnumAndNullable.Serialize);
-            Assert.Null(MixedModeContext.Default.ClassWithCustomConverter.Serialize);
-            Assert.Null(MixedModeContext.Default.StructWithCustomConverter.Serialize);
-            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterFactory.Serialize);
-            Assert.Null(MixedModeContext.Default.StructWithCustomConverterFactory.Serialize);
-            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterProperty.Serialize);
-            Assert.Null(MixedModeContext.Default.StructWithCustomConverterProperty.Serialize);
-            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterPropertyFactory.Serialize);
-            Assert.Null(MixedModeContext.Default.StructWithCustomConverterPropertyFactory.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MixedModeContext.Default.ClassWithBadCustomConverter.Serialize);
-            Assert.Throws<InvalidOperationException>(() => MixedModeContext.Default.StructWithBadCustomConverter.Serialize);
+            Assert.Null(MixedModeContext.Default.Location.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.NumberTypes.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.IndexViewModel.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.EmptyPoco.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.HighLowTemps.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyType.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyType2.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyTypeWithCallbacks.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyTypeWithPropertyOrdering.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyNestedClass.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.SampleEnum.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.String.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.NotNull(MixedModeContext.Default.ClassWithEnumAndNullable.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.ClassWithCustomConverter.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.StructWithCustomConverter.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.StructWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.StructWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.ClassWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Null(MixedModeContext.Default.StructWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MixedModeContext.Default.ClassWithBadCustomConverter.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => MixedModeContext.Default.StructWithBadCustomConverter.SerializeHandler);
         }
 
         [Fact]
index 8681cc7..520be63 100644 (file)
@@ -198,7 +198,7 @@ namespace System.Text.Json.SourceGeneration.Tests
             };
 
             // Types with properties in custom converters do not support fast path serialization.
-            Assert.True(DefaultContext.ClassWithCustomConverterProperty.Serialize is null);
+            Assert.True(DefaultContext.ClassWithCustomConverterProperty.SerializeHandler is null);
 
             if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization)
             {
@@ -225,7 +225,7 @@ namespace System.Text.Json.SourceGeneration.Tests
             };
 
             // Types with properties in custom converters do not support fast path serialization.
-            Assert.True(DefaultContext.StructWithCustomConverterProperty.Serialize is null);
+            Assert.True(DefaultContext.StructWithCustomConverterProperty.SerializeHandler is null);
 
             if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization)
             {
@@ -757,13 +757,15 @@ namespace System.Text.Json.SourceGeneration.Tests
 
         internal class CustomContext : JsonSerializerContext
         {
-            public CustomContext(JsonSerializerOptions options) : base(options, null) { }
+            public CustomContext(JsonSerializerOptions options) : base(options) { }
 
             private JsonTypeInfo<object> _object;
             public JsonTypeInfo<object> Object => _object ??= JsonMetadataServices.CreateValueInfo<object>(Options, JsonMetadataServices.ObjectConverter);
 
             private JsonTypeInfo<object[]> _objectArray;
-            public JsonTypeInfo<object[]> ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo<object>(Options, Object, default, serializeFunc: null);
+            public JsonTypeInfo<object[]> ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo<object>(Options, new JsonCollectionInfoValues<object[]> { ElementInfo = Object });
+
+            protected override JsonSerializerOptions? GeneratedSerializerOptions => null;
 
             public override JsonTypeInfo GetTypeInfo(Type type)
             {
@@ -780,7 +782,7 @@ namespace System.Text.Json.SourceGeneration.Tests
         {
             using MemoryStream ms = new();
             using Utf8JsonWriter writer = new(ms);
-            typeInfo.Serialize!(writer, value);
+            typeInfo.SerializeHandler!(writer, value);
             writer.Flush();
 
             JsonTestHelper.AssertJsonEqual(expectedJson, Encoding.UTF8.GetString(ms.ToArray()));
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs
new file mode 100644 (file)
index 0000000..4a27daa
--- /dev/null
@@ -0,0 +1,44 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Collections.Generic;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+using System.Text.Json.Serialization.Tests;
+using System.Text.Json.Serialization.Tests.Schemas.OrderPayload;
+
+namespace System.Text.Json.SourceGeneration.Tests
+{
+    public sealed partial class NodeInteropTests_Metadata : NodeInteropTests
+    {
+        public NodeInteropTests_Metadata()
+            : base(new StringSerializerWrapper(NodeInteropTestsContext_Metadata.Default, (options) => new NodeInteropTestsContext_Metadata(options)))
+        {
+        }
+
+        [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+        [JsonSerializable(typeof(List<Order>))]
+        [JsonSerializable(typeof(JsonArray))]
+        [JsonSerializable(typeof(Poco))]
+        [JsonSerializable(typeof(string))]
+        internal sealed partial class NodeInteropTestsContext_Metadata : JsonSerializerContext
+        {
+        }
+    }
+
+    public sealed partial class NodeInteropTests_Default : NodeInteropTests
+    {
+        public NodeInteropTests_Default()
+            : base(new StringSerializerWrapper(NodeInteropTestsContext_Default.Default, (options) => new NodeInteropTestsContext_Default(options)))
+        {
+        }
+
+        [JsonSerializable(typeof(List<Order>))]
+        [JsonSerializable(typeof(JsonArray))]
+        [JsonSerializable(typeof(Poco))]
+        [JsonSerializable(typeof(string))]
+        internal sealed partial class NodeInteropTestsContext_Default : JsonSerializerContext
+        {
+        }
+    }
+}
index 639f380..5f4b0dc 100644 (file)
@@ -128,35 +128,35 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.NotNull(SerializationContext.Default.Location.Serialize);
-            Assert.NotNull(SerializationContext.Default.RepeatedLocation.Serialize);
-            Assert.NotNull(SerializationContext.Default.NumberTypes.Serialize);
-            Assert.NotNull(SerializationContext.Default.ActiveOrUpcomingEvent.Serialize);
-            Assert.NotNull(SerializationContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.NotNull(SerializationContext.Default.IndexViewModel.Serialize);
-            Assert.NotNull(SerializationContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(SerializationContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(SerializationContext.Default.HighLowTemps.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyType.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyType2.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyTypeWithCallbacks.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyTypeWithPropertyOrdering.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyIntermediateType.Serialize);
-            Assert.NotNull(SerializationContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyNestedClass.Serialize);
-            Assert.NotNull(SerializationContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(SerializationContext.Default.ObjectArray.Serialize);
-            Assert.Null(SerializationContext.Default.String.Serialize);
-            Assert.NotNull(SerializationContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.NotNull(SerializationContext.Default.ClassWithEnumAndNullable.Serialize);
-            Assert.Null(SerializationContext.Default.ClassWithCustomConverter.Serialize);
-            Assert.Null(SerializationContext.Default.StructWithCustomConverter.Serialize);
-            Assert.Null(SerializationContext.Default.ClassWithCustomConverterFactory.Serialize);
-            Assert.Null(SerializationContext.Default.StructWithCustomConverterFactory.Serialize);
-            Assert.Null(SerializationContext.Default.ClassWithCustomConverterProperty.Serialize);
-            Assert.Null(SerializationContext.Default.StructWithCustomConverterProperty.Serialize);
-            Assert.Throws<InvalidOperationException>(() => SerializationContext.Default.ClassWithBadCustomConverter.Serialize);
-            Assert.Throws<InvalidOperationException>(() => SerializationContext.Default.StructWithBadCustomConverter.Serialize);
+            Assert.NotNull(SerializationContext.Default.Location.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.NumberTypes.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.ActiveOrUpcomingEvent.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.IndexViewModel.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.HighLowTemps.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyType.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyType2.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyTypeWithCallbacks.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyTypeWithPropertyOrdering.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyNestedClass.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(SerializationContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(SerializationContext.Default.String.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.NotNull(SerializationContext.Default.ClassWithEnumAndNullable.SerializeHandler);
+            Assert.Null(SerializationContext.Default.ClassWithCustomConverter.SerializeHandler);
+            Assert.Null(SerializationContext.Default.StructWithCustomConverter.SerializeHandler);
+            Assert.Null(SerializationContext.Default.ClassWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(SerializationContext.Default.StructWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(SerializationContext.Default.ClassWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(SerializationContext.Default.StructWithCustomConverterProperty.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => SerializationContext.Default.ClassWithBadCustomConverter.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => SerializationContext.Default.StructWithBadCustomConverter.SerializeHandler);
         }
 
         [Fact]
@@ -398,35 +398,35 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public override void EnsureFastPathGeneratedAsExpected()
         {
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.Location.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.RepeatedLocation.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.IndexViewModel.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTemps.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType2.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyIntermediateType.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTempsImmutable.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedClass.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedNestedClass.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.SampleEnum.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.Serialize);
-            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverter.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverter.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterPropertyFactory.Serialize);
-            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterPropertyFactory.Serialize);
-            Assert.Throws<InvalidOperationException>(() => SerializationWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.Serialize);
-            Assert.Throws<InvalidOperationException>(() => SerializationWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.Serialize);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.Location.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.RepeatedLocation.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ActiveOrUpcomingEvent.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.CampaignSummaryViewModel.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.IndexViewModel.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.WeatherForecastWithPOCOs.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTemps.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyType2.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyIntermediateType.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.HighLowTempsImmutable.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedClass.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.MyNestedNestedClass.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ObjectArray.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.SampleEnum.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.String.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ValueTupleStringInt32Boolean.SerializeHandler);
+            Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverter.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverter.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterFactory.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterProperty.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.ClassWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Null(SerializationWithPerTypeAttributeContext.Default.StructWithCustomConverterPropertyFactory.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => SerializationWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler);
+            Assert.Throws<InvalidOperationException>(() => SerializationWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler);
         }
     }
 }
index a086659..2bfb070 100644 (file)
@@ -52,11 +52,11 @@ namespace System.Text.Json.SourceGeneration.Tests
         [Fact]
         public static void DictionaryFastPathPrimitiveValueSupported()
         {
-            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringString.Serialize);
-            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringJsonMessage.Serialize);
-            Assert.NotNull(DictionaryTypeContext.Default.JsonMessage.Serialize);
-            Assert.Null(DictionaryTypeContext.Default.String.Serialize);
-            Assert.Null(DictionaryTypeContext.Default.Int32.Serialize);
+            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringString.SerializeHandler);
+            Assert.NotNull(DictionaryTypeContext.Default.DictionaryStringJsonMessage.SerializeHandler);
+            Assert.NotNull(DictionaryTypeContext.Default.JsonMessage.SerializeHandler);
+            Assert.Null(DictionaryTypeContext.Default.String.SerializeHandler);
+            Assert.Null(DictionaryTypeContext.Default.Int32.SerializeHandler);
         }
 
         // Options with features that apply only to deserialization.
index 71681de..b16e2cc 100644 (file)
     <Compile Include="..\Common\JsonSerializerWrapperForStream.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForStream.cs" />
     <Compile Include="..\Common\JsonSerializerWrapperForString.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForString.cs" />
     <Compile Include="..\Common\JsonTestHelper.cs" Link="CommonTest\System\Text\Json\JsonTestHelper.cs" />
+    <Compile Include="..\Common\NodeInteropTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\NodeInteropTests.cs" />
     <Compile Include="..\Common\PropertyNameTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyNameTests.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.InitOnly.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.InitOnly.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.NonPublicAccessors.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.NonPublicAccessors.cs" />
+    <Compile Include="..\Common\SampleTestData.OrderPayload.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\SampleTestData.OrderPayload.cs" />
     <Compile Include="..\Common\SerializerTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\SerializerTests.cs" />
     <Compile Include="..\Common\TestClasses\TestClasses.ConcurrentCollections.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\TestClasses\TestClasses.ConcurrentCollections.cs" />
     <Compile Include="..\Common\TestClasses\TestClasses.Constructor.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\TestClasses\TestClasses.Constructor.cs" />
@@ -75,6 +77,7 @@
     <Compile Include="RealWorldContextTests.cs" />
     <Compile Include="SerializationContextTests.cs" />
     <Compile Include="SerializationLogicTests.cs" />
+    <Compile Include="Serialization\NodeInteropTests.cs" />
     <Compile Include="Serialization\PropertyNameTests.cs" />
     <Compile Include="Serialization\PropertyVisibilityTests.cs" />
     <Compile Include="Serialization\UnsupportedTypesTests.cs" />
index aeb4c30..515579f 100644 (file)
@@ -61,9 +61,10 @@ public abstract class JsonSerializerApiValidation
 
     internal partial class MyDummyContext : JsonSerializerContext
     {
-        public MyDummyContext() : base(new JsonSerializerOptions(), new JsonSerializerOptions()) { }
-        public MyDummyContext(JsonSerializerOptions options) : base(options, new JsonSerializerOptions()) { }
+        public MyDummyContext() : base(new JsonSerializerOptions()) { }
+        public MyDummyContext(JsonSerializerOptions options) : base(options) { }
         public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException();
+        protected override JsonSerializerOptions? GeneratedSerializerOptions => null;
     }
 
     private JsonTypeInfo<MyPoco> myDummyTypeInfo = GetTypeInfo();
index c25e780..567a277 100644 (file)
@@ -89,17 +89,20 @@ namespace System.Text.Json.Serialization.Tests
 
         private class MyJsonContext : JsonSerializerContext
         {
-            public MyJsonContext() : base(null, null) { }
+            public MyJsonContext() : base(null) { }
 
-            public MyJsonContext(JsonSerializerOptions options) : base(options, null) { }
+            public MyJsonContext(JsonSerializerOptions options) : base(options) { }
 
             public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException();
+
+            protected override JsonSerializerOptions? GeneratedSerializerOptions => null;
         }
 
         private class MyJsonContextThatSetsOptionsInParameterlessCtor : JsonSerializerContext
         {
-            public MyJsonContextThatSetsOptionsInParameterlessCtor() : base(new JsonSerializerOptions(), null) { }
+            public MyJsonContextThatSetsOptionsInParameterlessCtor() : base(new JsonSerializerOptions()) { }
             public override JsonTypeInfo? GetTypeInfo(Type type) => throw new NotImplementedException();
+            protected override JsonSerializerOptions? GeneratedSerializerOptions => null;
         }
     }
 }
diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs
new file mode 100644 (file)
index 0000000..a424cb8
--- /dev/null
@@ -0,0 +1,10 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Text.Json.Serialization.Tests
+{
+    public sealed partial class NodeInteropTestsDynamic : NodeInteropTests
+    {
+        public NodeInteropTestsDynamic() : base(JsonSerializerWrapperForString.StringSerializer) { }
+    }
+}
index 35d9610..d7e6e92 100644 (file)
@@ -289,7 +289,7 @@ namespace System.Text.Json.Serialization.Tests
         [InlineData(1000, false, false)]
         public async Task VeryLargeJsonFileTest(int payloadSize, bool ignoreNull, bool writeIndented)
         {
-            List<Order> list = PopulateLargeObject(payloadSize);
+            List<Order> list = JsonTestHelper.PopulateLargeObject(payloadSize);
 
             JsonSerializerOptions options = new JsonSerializerOptions
             {
@@ -337,10 +337,10 @@ namespace System.Text.Json.Serialization.Tests
 
             int length = ListLength * depthFactor;
             List<Order>[] orders = new List<Order>[length];
-            orders[0] = PopulateLargeObject(1);
+            orders[0] = JsonTestHelper.PopulateLargeObject(1);
             for (int i = 1; i < length; i++ )
             {
-                orders[i] = PopulateLargeObject(1);
+                orders[i] = JsonTestHelper.PopulateLargeObject(1);
                 orders[i - 1][0].RelatedOrder = orders[i];
             }
 
@@ -381,10 +381,10 @@ namespace System.Text.Json.Serialization.Tests
 
             int length = ListLength * depthFactor;
             List<Order>[] orders = new List<Order>[length];
-            orders[0] = PopulateLargeObject(1000);
+            orders[0] = JsonTestHelper.PopulateLargeObject(1000);
             for (int i = 1; i < length; i++)
             {
-                orders[i] = PopulateLargeObject(1);
+                orders[i] = JsonTestHelper.PopulateLargeObject(1);
                 orders[i - 1][0].RelatedOrder = orders[i];
             }
 
@@ -464,188 +464,6 @@ namespace System.Text.Json.Serialization.Tests
             }
             return list;
         }
-
-        internal static List<Order> PopulateLargeObject(int size)
-        {
-            List<Order> orders = new List<Order>(size);
-            for (int i = 0; i < size; i++)
-            {
-                Order order = new Order
-                {
-                    OrderNumber = i,
-                    Customer = new User
-                    {
-                        UserId = "222ffbbb888kkk",
-                        Name = "John Doe",
-                        Username = "johndoe",
-                        CreatedAt = new DateTime(),
-                        ImageId = string.Empty,
-                        UserType = UserType.Customer,
-                        UpdatedAt = new DateTime(),
-                        TwitterId = string.Empty,
-                        FacebookId = "9988998877662222111",
-                        SubscriptionType = 2,
-                        IsNew = true,
-                        IsEmployee = false
-                    },
-                    ShippingInfo = new List<ShippingInfo>
-                    {
-                        new ShippingInfo()
-                        {
-                            OrderNumber = i,
-                            Employee = new User
-                            {
-                                UserId = "222ffbbb888" + i,
-                                Name = "Shipping Coordinator",
-                                Username = "coordinator" + i,
-                                CreatedAt = new DateTime(),
-                                ImageId = string.Empty,
-                                UserType = UserType.Employee,
-                                UpdatedAt = new DateTime(),
-                                TwitterId = string.Empty,
-                                SubscriptionType = 0,
-                                IsEmployee = true
-                            },
-                            CarrierId = "TTT123999MMM",
-                            ShippingType = "Ground",
-                            EstimatedDelivery = new DateTime(),
-                            Tracking = new Uri("http://TestShipCompany.test/track/123" + i),
-                            CarrierName = "TestShipCompany",
-                            HandlingInstruction = "Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats. Do cats eat bats? Do cats eat bats",
-                            CurrentStatus = "Out for delivery",
-                            IsDangerous = false
-                        }
-                    },
-                    OneTime = true,
-                    Cancelled = false,
-                    IsGift = i % 2 == 0,
-                    IsGPickUp = i % 5 == 0,
-                    ShippingAddress = new Address()
-                    {
-                        City = "Redmond"
-                    },
-                    PickupAddress = new Address
-                    {
-                        City = "Bellevue"
-                    },
-                    Coupon = SampleEnumInt64.Max,
-                    UserInteractions = new List<Comment>
-                    {
-                        new Comment
-                        {
-                            Id = 200 + i,
-                            OrderNumber = i,
-                            Customer = new User
-                            {
-                                UserId = "222ffbbb888kkk",
-                                Name = "John Doe",
-                                Username = "johndoe",
-                                CreatedAt = new DateTime(),
-                                ImageId = string.Empty,
-                                UserType = UserType.Customer,
-                                UpdatedAt = new DateTime(),
-                                TwitterId = "twitterId" + i,
-                                FacebookId = "9988998877662222111",
-                                SubscriptionType = 2,
-                                IsNew = true,
-                                IsEmployee = false
-                            },
-                            Title = "Green Field",
-                            Message = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to",
-                            Responses = new List<Comment>()
-                        }
-                    },
-                    Created = new DateTime(2019, 11, 10),
-                    Confirmed = new DateTime(2019, 11, 11),
-                    ShippingDate = new DateTime(2019, 11, 12),
-                    EstimatedDelivery = new DateTime(2019, 11, 15),
-                    ReviewedBy = new User()
-                    {
-                        UserId = "222ffbbb888" + i,
-                        Name = "Shipping Coordinator",
-                        Username = "coordinator" + i,
-                        CreatedAt = new DateTime(),
-                        ImageId = string.Empty,
-                        UserType = UserType.Employee,
-                        UpdatedAt = new DateTime(),
-                        TwitterId = string.Empty,
-                        SubscriptionType = 0,
-                        IsEmployee = true
-                    }
-                };
-                List<Product> products = new List<Product>();
-                for (int j = 0; j < i % 4; j++)
-                {
-                    Product product = new Product()
-                    {
-                        ProductId = Guid.NewGuid(),
-                        Name = "Surface Pro",
-                        SKU = "LL123" + j,
-                        Brand = new TestClassWithInitializedProperties(),
-                        ProductCategory = new SimpleTestClassWithNonGenericCollectionWrappers(),
-                        Description = "Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time. I think-' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '-yes, that's about the right distance-but then I wonder what Latitude or Longitude I've got to",
-                        Created = new DateTime(2000, 10, 12),
-                        Title = "Surface Pro 6 for Business - 512GB",
-                        Price = new Price(),
-                        BestChoice = true,
-                        AverageStars = 4.8f,
-                        Featured = true,
-                        ProductRestrictions = new TestClassWithInitializedProperties(),
-                        SalesInfo = new SimpleTestClassWithGenericCollectionWrappers(),
-                        Origin = SampleEnum.One,
-                        Manufacturer = new BasicCompany(),
-                        Fragile = true,
-                        DetailsUrl = new Uri("http://dotnet.test/link/entries/entry/1"),
-                        NetWeight = 2.7m,
-                        GrossWeight = 3.3m,
-                        Length = i,
-                        Height = i + 1,
-                        Width = i + 2,
-                        FeaturedImage = new FeaturedImage(),
-                        PreviewImage = new PreviewImage(),
-                        KeyWords = new List<string> { "surface", "pro", "laptop" },
-                        RelatedImages = new List<Image>(),
-                        RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"),
-                        GuaranteeStartsAt = new DateTime(),
-                        GuaranteeEndsAt = new DateTime(),
-                        IsActive = true,
-                        RelatedProducts = new List<Product>()
-                    };
-                    product.SalesInfo.Initialize();
-                    List<Review> reviews = new List<Review>();
-                    for (int k = 0; k < i % 3; k++)
-                    {
-
-                        Review review = new Review
-                        {
-                            Customer = new User
-                            {
-                                UserId = "333344445555",
-                                Name = "Customer" + i + k,
-                                Username = "cust" + i + k,
-                                CreatedAt = new DateTime(),
-                                ImageId = string.Empty,
-                                UserType = UserType.Customer,
-                                SubscriptionType = k
-                            },
-                            ProductSku = product.SKU,
-                            CustomerName = "Customer" + i + k,
-                            Stars = j + k,
-                            Title = $"Title {i}{j}{k}",
-                            Comment = "",
-                            Images = new List<Uri>{ new Uri($"http://dotnet.test/link/images/image/{k}"), new Uri($"http://dotnet.test/link/images/image/{j}")},
-                            ReviewId = i + j +k
-                        };
-                        reviews.Add(review);
-                    }
-                    product.Reviews = reviews;
-                    products.Add(product);
-                }
-                order.Products = products;
-                orders.Add(order);
-            }
-            return orders;
-        }
     }
 
     public sealed class TestStream : Stream
index b194b44..037d2b2 100644 (file)
     <Compile Include="..\Common\JsonSerializerWrapperForStream.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForStream.cs" />
     <Compile Include="..\Common\JsonSerializerWrapperForString.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\JsonSerializerWrapperForString.cs" />
     <Compile Include="..\Common\JsonTestHelper.cs" Link="CommonTest\System\Text\Json\JsonTestHelper.cs" />
+    <Compile Include="..\Common\NodeInteropTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\NodeInteropTests.cs" />
     <Compile Include="..\Common\PropertyNameTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyNameTests.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.InitOnly.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.InitOnly.cs" />
     <Compile Include="..\Common\PropertyVisibilityTests.NonPublicAccessors.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\PropertyVisibilityTests.NonPublicAccessors.cs" />
+    <Compile Include="..\Common\SampleTestData.OrderPayload.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\SampleTestData.OrderPayload.cs" />
     <Compile Include="..\Common\SerializerTests.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\SerializerTests.cs" />
     <Compile Include="..\Common\TestClasses\TestClasses.ConcurrentCollections.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\TestClasses\TestClasses.ConcurrentCollections.cs" />
     <Compile Include="..\Common\TestClasses\TestClasses.Constructor.cs" Link="CommonTest\System\Text\Json\Tests\Serialization\TestClasses\TestClasses.Constructor.cs" />
@@ -88,7 +90,6 @@
     <Compile Include="JsonNode\JsonValueTests.cs" />
     <Compile Include="JsonNode\ParseTests.cs" />
     <Compile Include="JsonNode\ParentPathRootTests.cs" />
-    <Compile Include="JsonNode\SerializerInteropTests.cs" />
     <Compile Include="JsonNode\ToStringTests.cs" />
     <Compile Include="JsonNumberTestData.cs" />
     <Compile Include="JsonPropertyTests.cs" />
     <Compile Include="Serialization\MetadataTests\MetadataTests.cs" />
     <Compile Include="Serialization\MetadataTests\MetadataTests.JsonSerializer.cs" />
     <Compile Include="Serialization\MetadataTests\MetadataTests.Options.cs" />
+    <Compile Include="Serialization\NodeInteropTests.cs" />
     <Compile Include="Serialization\Null.ReadTests.cs" />
     <Compile Include="Serialization\Null.WriteTests.cs" />
     <Compile Include="Serialization\NullableTests.cs" />
     <Compile Include="Serialization\ReferenceHandlerTests.Deserialize.cs" />
     <Compile Include="Serialization\ReferenceHandlerTests.IgnoreCycles.cs" />
     <Compile Include="Serialization\ReferenceHandlerTests.Serialize.cs" />
-    <Compile Include="Serialization\SampleTestData.OrderPayload.cs" />
     <Compile Include="Serialization\SpanTests.cs" />
     <Compile Include="Serialization\StreamTests.cs" />
     <Compile Include="Serialization\Stream.Collections.cs" />
index 15a4964..3dfd069 100644 (file)
     <!-- https://github.com/dotnet/runtime/issues/58226 -->
     <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Unit.Tests.csproj" />
     <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Unit.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Unit.Tests.csproj" />
+
+    <!-- https://github.com/dotnet/runtime/issues/59228 -->
+    <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj" />
+    <ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Text.Json\tests\System.Text.Json.SourceGeneration.Tests\System.Text.Json.SourceGeneration.Roslyn4.0.Tests.csproj" />
   </ItemGroup>
 
   <!-- Aggressive Trimming related failures -->