From 52324feefa147b5e3038e8886b2fd0f071989b6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 18 Sep 2021 10:12:04 -0600 Subject: [PATCH] [release/6.0-rc2] Update source-gen APIs according to review (#59243) * 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 Co-authored-by: Layomi Akinrinade --- .../Common/JsonSourceGenerationOptionsAttribute.cs | 5 - .../gen/JsonSourceGenerator.Emitter.cs | 213 +++++----- .../gen/JsonSourceGenerator.Parser.cs | 26 +- .../System.Text.Json/gen/TypeGenerationSpec.cs | 9 - .../System.Text.Json/ref/System.Text.Json.cs | 97 +++-- .../System.Text.Json/src/System.Text.Json.csproj | 18 +- .../Converters/JsonMetadataServicesConverter.cs | 6 +- .../Converters/Node/JsonNodeConverter.cs | 2 +- .../Serialization/JsonSerializer.Write.Helpers.cs | 4 +- .../Json/Serialization/JsonSerializerContext.cs | 73 ++-- .../JsonCollectionInfoValuesOfTCollection.cs | 37 ++ .../Metadata/JsonMetadataServices.Collections.cs | 466 +++++++-------------- .../Metadata/JsonMetadataServices.Converters.cs | 24 +- .../Serialization/Metadata/JsonMetadataServices.cs | 70 +--- ...ectInfoValues.cs => JsonObjectInfoValuesOfT.cs} | 0 .../Serialization/Metadata/JsonPropertyInfoOfT.cs | 61 ++- .../Metadata/JsonPropertyInfoValuesOfT.cs | 82 ++++ .../Json/Serialization/Metadata/JsonTypeInfo.cs | 2 +- .../Metadata/JsonTypeInfoInternalOfT.cs | 67 +-- .../Json/Serialization/Metadata/JsonTypeInfoOfT.cs | 9 +- .../CollectionTests.Dictionary.NonStringKey.cs | 19 +- .../tests/Common/JsonTestHelper.cs | 184 ++++++++ .../NodeInteropTests.cs} | 24 +- .../SampleTestData.OrderPayload.cs | 0 .../ContextClasses.cs | 6 +- .../MetadataAndSerializationContextTests.cs | 44 +- .../MetadataContextTests.cs | 124 +++--- .../MixedModeContextTests.cs | 62 +-- .../RealWorldContextTests.cs | 12 +- .../Serialization/NodeInteropTests.cs | 44 ++ .../SerializationContextTests.cs | 116 ++--- .../SerializationLogicTests.cs | 10 +- ...System.Text.Json.SourceGeneration.Tests.targets | 3 + .../Serialization/JsonSerializerApiValidation.cs | 5 +- .../MetadataTests/MetadataTests.Options.cs | 9 +- .../Serialization/NodeInteropTests.cs | 10 + .../Serialization/Stream.WriteTests.cs | 192 +-------- .../System.Text.Json.Tests.csproj | 5 +- src/libraries/tests.proj | 4 + 39 files changed, 1075 insertions(+), 1069 deletions(-) create mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs rename src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/{JsonObjectInfoValues.cs => JsonObjectInfoValuesOfT.cs} (100%) create mode 100644 src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs rename src/libraries/System.Text.Json/tests/{System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs => Common/NodeInteropTests.cs} (65%) rename src/libraries/System.Text.Json/tests/{System.Text.Json.Tests/Serialization => Common}/SampleTestData.OrderPayload.cs (100%) create mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs create mode 100644 src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs diff --git a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs index 84ffc3d..45f11a4 100644 --- a/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs +++ b/src/libraries/System.Text.Json/Common/JsonSourceGenerationOptionsAttribute.cs @@ -31,11 +31,6 @@ namespace System.Text.Json.Serialization public bool IgnoreReadOnlyProperties { get; set; } /// - /// Specifies whether to ignore custom converters provided at run time. - /// - public bool IgnoreRuntimeCustomConverters { get; set; } - - /// /// Specifies whether to include fields for serialization and deserialization. /// public bool IncludeFields { get; set; } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index 131e08d..217aed6 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -23,13 +23,18 @@ 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) {{ diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index 9ba0372..e5cb105 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -25,9 +25,12 @@ 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); diff --git a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs index 02d51cd..1b83543 100644 --- a/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs +++ b/src/libraries/System.Text.Json/gen/TypeGenerationSpec.cs @@ -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 diff --git a/src/libraries/System.Text.Json/ref/System.Text.Json.cs b/src/libraries/System.Text.Json/ref/System.Text.Json.cs index 23b6322..77d6c85 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -798,7 +798,7 @@ 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 + { + public JsonCollectionInfoValues() { } + public System.Func? ObjectCreator { get { throw null; } init { } } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo ElementInfo { get { throw null; } init { } } + public System.Text.Json.Serialization.Metadata.JsonTypeInfo? KeyInfo { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } } + public System.Action? SerializeHandler { get { throw null; } init { } } + } public static partial class JsonMetadataServices { public static System.Text.Json.Serialization.JsonConverter BooleanConverter { get { throw null; } } @@ -962,8 +971,11 @@ namespace System.Text.Json.Serialization.Metadata public static System.Text.Json.Serialization.JsonConverter Int16Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter Int32Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter Int64Converter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonArrayConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter JsonElementConverter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonNodeConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter JsonObjectConverter { get { throw null; } } + public static System.Text.Json.Serialization.JsonConverter JsonValueConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter ObjectConverter { get { throw null; } } [System.CLSCompliantAttribute(false)] public static System.Text.Json.Serialization.JsonConverter SByteConverter { get { throw null; } } @@ -978,27 +990,28 @@ namespace System.Text.Json.Serialization.Metadata public static System.Text.Json.Serialization.JsonConverter UInt64Converter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter UriConverter { get { throw null; } } public static System.Text.Json.Serialization.JsonConverter VersionConverter { get { throw null; } } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateArrayInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentQueue { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentStackInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Concurrent.ConcurrentStack { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo keyInfo, System.Text.Json.Serialization.Metadata.JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Dictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateICollectionInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.ICollection { throw null; } - public static JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo stringInfo, JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IDictionary { throw null; } - public static JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IEnumerable { throw null; } - public static JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } - public static JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo objectInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.IList { throw null; } - public static JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IList { throw null; } - public static JsonTypeInfo CreateImmutableDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Func>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateImmutableEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Func, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } - public static JsonTypeInfo CreateIReadOnlyDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, JsonTypeInfo keyInfo, JsonTypeInfo valueInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } - public static JsonTypeInfo CreateISetInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.ISet { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateListInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.List { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateArrayInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentQueue { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateConcurrentStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Concurrent.ConcurrentStack { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Dictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateICollectionInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.ICollection { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IDictionary { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.IList { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IList { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateImmutableDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Func>, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateImmutableEnumerableInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Func, TCollection> createRangeFunc) where TCollection : System.Collections.Generic.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateIReadOnlyDictionaryInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.IReadOnlyDictionary where TKey : notnull { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateISetInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.ISet { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateListInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.List { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateObjectInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonObjectInfoValues objectInfo) where T : notnull { throw null; } - public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo(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? converter, System.Func? getter, System.Action? 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 CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Queue { throw null; } - public static JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc) where TCollection : System.Collections.Generic.Stack { throw null; } - public static JsonTypeInfo CreateStackOrQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Func? createObjectFunc, System.Text.Json.Serialization.Metadata.JsonTypeInfo elementInfo, System.Text.Json.Serialization.JsonNumberHandling numberHandling, System.Action? serializeFunc, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonPropertyInfo CreatePropertyInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues propertyInfo) { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateQueueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Queue { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } + public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Stack { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateValueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) { throw null; } public static System.Text.Json.Serialization.JsonConverter GetUnsupportedTypeConverter() { throw null; } public static System.Text.Json.Serialization.JsonConverter GetEnumConverter(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 { - public System.Func? ConstructorParameterMetadataInitializer { get; init; } - public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get; init; } - public System.Func? ObjectCreator { get; init; } - public System.Func? ObjectWithParameterizedConstructorCreator { get; init; } - public System.Func? PropertyMetadataInitializer { get; init; } - public System.Action? SerializeHandler { get; init; } + public JsonObjectInfoValues() { } + public System.Func? ConstructorParameterMetadataInitializer { get { throw null; } init { } } + public System.Text.Json.Serialization.JsonNumberHandling NumberHandling { get { throw null; } init { } } + public System.Func? ObjectCreator { get { throw null; } init { } } + public System.Func? ObjectWithParameterizedConstructorCreator { get { throw null; } init { } } + public System.Func? PropertyMetadataInitializer { get { throw null; } init { } } + public System.Action? 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 + { + public JsonPropertyInfoValues() { } + public System.Text.Json.Serialization.JsonConverter? Converter { get { throw null; } init { } } + public System.Type DeclaringType { get { throw null; } init { } } + public System.Func? 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? 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 : System.Text.Json.Serialization.Metadata.JsonTypeInfo { internal JsonTypeInfo() { } - public System.Action? Serialize { get { throw null; } } + public System.Action? SerializeHandler { get { throw null; } } } } diff --git a/src/libraries/System.Text.Json/src/System.Text.Json.csproj b/src/libraries/System.Text.Json/src/System.Text.Json.csproj index 79eb67c..4b7f0bc 100644 --- a/src/libraries/System.Text.Json/src/System.Text.Json.csproj +++ b/src/libraries/System.Text.Json/src/System.Text.Json.csproj @@ -117,13 +117,6 @@ System.Text.Json.Utf8JsonReader - - - - - - - @@ -230,14 +223,23 @@ System.Text.Json.Utf8JsonReader + + + + + + - + + + + diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs index 9bc2f3b..5ee913f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/JsonMetadataServicesConverter.cs @@ -8,7 +8,7 @@ namespace System.Text.Json.Serialization.Converters { /// /// Provides a mechanism to invoke "fast-path" serialization logic via - /// . This type holds an optional + /// . This type holds an optional /// reference to an actual for the type /// , to provide a fallback when the fast path cannot be used. /// @@ -75,10 +75,10 @@ namespace System.Text.Json.Serialization.Converters if (!state.SupportContinuation && jsonTypeInfo is JsonTypeInfo info && - info.Serialize != null && + info.SerializeHandler != null && info.Options._context?.CanUseSerializationLogic == true) { - info.Serialize(writer, value); + info.SerializeHandler(writer, value); return true; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs index 8d0f7bb..5dd032c 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Node/JsonNodeConverter.cs @@ -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}. /// - internal sealed class JsonNodeConverter : JsonConverter + internal sealed class JsonNodeConverter : JsonConverter { private static JsonNodeConverter? s_nodeConverter; private static JsonArrayConverter? s_arrayConverter; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs index 4f10052..761798f 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Write.Helpers.cs @@ -43,8 +43,8 @@ namespace System.Text.Json jsonTypeInfo is JsonTypeInfo 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 diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs index 688fd91..0ce1818 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerContext.cs @@ -13,11 +13,31 @@ namespace System.Text.Json.Serialization public abstract partial class JsonSerializerContext { private bool? _canUseSerializationLogic; - private JsonSerializerOptions? _defaultOptions; internal JsonSerializerOptions? _options; /// + /// 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 instance cannot be mutated once it is bound with the context instance. + /// + public JsonSerializerOptions Options + { + get + { + if (_options == null) + { + _options = new JsonSerializerOptions(); + _options._context = this; + } + + return _options; + } + } + + /// /// Indicates whether pre-generated serialization logic for types in the context /// is compatible with the run time specified . /// @@ -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 } /// - /// 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 . /// - /// - /// The instance cannot be mutated once it is bound with the context instance. - /// - public JsonSerializerOptions Options - { - get - { - if (_options == null) - { - _options = new JsonSerializerOptions(); - _options._context = this; - } - - return _options; - } - } + protected abstract JsonSerializerOptions? GeneratedSerializerOptions { get; } /// /// Creates an instance of and binds it with the indicated . /// - /// The run time provided options for the context instance. - /// The default run time options for the context. Its values are defined at design-time via . + /// The run time provided options for the context instance. /// /// If no instance options are passed, then no options are set until the context is bound using , /// or until is called, where a new options instance is created and bound. /// - 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; } /// 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 index 0000000..b1fef6a --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonCollectionInfoValuesOfTCollection.cs @@ -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 +{ + /// + /// Provides serialization metadata about a collection type. + /// + /// The collection type. + public sealed class JsonCollectionInfoValues + { + /// + /// A to create an instance of the collection when deserializing. + /// + public Func? ObjectCreator { get; init; } + + /// + /// If a dictionary type, the instance representing the key type. + /// + public JsonTypeInfo? KeyInfo { get; init; } + + /// + /// A instance representing the element type. + /// + public JsonTypeInfo ElementInfo { get; init; } = null!; + + /// + /// The option to apply to number collection elements. + /// + public JsonNumberHandling NumberHandling { get; init; } + + /// + /// An optimized serialization implementation assuming pre-determined defaults. + /// + public Action? SerializeHandler { get; init; } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs index 71f48ad..4b17086 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Collections.cs @@ -11,552 +11,368 @@ namespace System.Text.Json.Serialization.Metadata public static partial class JsonMetadataServices { /// - /// Creates metadata for an array. + /// Creates serialization metadata for an array. /// /// The generic definition of the element type. /// The to use. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// - public static JsonTypeInfo CreateArrayInfo( - JsonSerializerOptions options, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. + public static JsonTypeInfo CreateArrayInfo(JsonSerializerOptions options, JsonCollectionInfoValues collectionInfo) => new JsonTypeInfoInternal( options, - createObjectFunc: null, - () => new ArrayConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ArrayConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. - /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// The to use. + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : List => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ListOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ListOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Dictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new DictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new DictionaryOfTKeyTValueConverter()); #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for and + /// Creates serialization metadata for and /// types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method to create an immutable dictionary instance. - /// + /// Serialization metadata for the given type. #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved public static JsonTypeInfo CreateImmutableDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Func>, TCollection> createRangeFunc) where TCollection : IReadOnlyDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new ImmutableDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue), - createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); + createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new IDictionaryOfTKeyTValueConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the key type. /// The generic definition of the value type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the key type. - /// A instance representing the value type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIReadOnlyDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo keyInfo, - JsonTypeInfo valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IReadOnlyDictionary where TKey : notnull => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IReadOnlyDictionaryOfTKeyTValueConverter(), - keyInfo, - valueInfo, - numberHandling, - serializeFunc, - typeof(TKey), - typeof(TValue)); + collectionInfo, + () => new IReadOnlyDictionaryOfTKeyTValueConverter()); #pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for non-dictionary immutable collection types. + /// Creates serialization metadata for non-dictionary immutable collection types. /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method to create an immutable dictionary instance. - /// + /// Serialization metadata for the given type. #pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved public static JsonTypeInfo CreateImmutableEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Func, TCollection> createRangeFunc) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new ImmutableEnumerableOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement), - createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); + createObjectWithArgs: createRangeFunc ?? throw new ArgumentNullException(nameof(createRangeFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo objectInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IList => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IListConverter(), - objectInfo, - numberHandling, - serializeFunc, - typeof(object)); + collectionInfo, + () => new IListConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIListInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IList => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IListOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new IListOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateISetInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ISet => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ISetOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ISetOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateICollectionInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ICollection => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ICollectionOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ICollectionOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateStackInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Stack => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new StackOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new StackOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : Queue => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new QueueOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new QueueOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateConcurrentStackInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ConcurrentStack => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ConcurrentStackOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ConcurrentStackOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateConcurrentQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : ConcurrentQueue => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new ConcurrentQueueOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new ConcurrentQueueOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// The generic definition of the element type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IEnumerableOfTConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(TElement)); + collectionInfo, + () => new IEnumerableOfTConverter()); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing instances. - /// A instance representing instances. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIDictionaryInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo stringInfo, - JsonTypeInfo objectInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IDictionary => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IDictionaryConverter(), - keyInfo: stringInfo, - valueInfo: objectInfo, - numberHandling, - serializeFunc, - typeof(string), - typeof(object)); + collectionInfo, + () => new IDictionaryConverter()); + +#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved + /// + /// Creates serialization metadata for types. + /// + /// The generic definition of the type. + /// + /// Provides serialization metadata about the collection type. + /// A method for adding elements to the collection when using the serializer's code-paths. + /// Serialization metadata for the given type. +#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved + public static JsonTypeInfo CreateStackInfo( + JsonSerializerOptions options, + JsonCollectionInfoValues collectionInfo, + Action addFunc) + where TCollection : IEnumerable + => CreateStackOrQueueInfo(options, collectionInfo, addFunc); +#pragma warning disable CS1574 // XML comment has cref attribute that could not be resolved /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types. /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. + /// Provides serialization metadata about the collection type. /// A method for adding elements to the collection when using the serializer's code-paths. - /// - public static JsonTypeInfo CreateStackOrQueueInfo( + /// Serialization metadata for the given type. +#pragma warning restore CS1574 // XML comment has cref attribute that could not be resolved + public static JsonTypeInfo CreateQueueInfo( + JsonSerializerOptions options, + JsonCollectionInfoValues collectionInfo, + Action addFunc) + where TCollection : IEnumerable + => CreateStackOrQueueInfo(options, collectionInfo, addFunc); + + private static JsonTypeInfo CreateStackOrQueueInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, + JsonCollectionInfoValues collectionInfo, Action addFunc) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, + collectionInfo, () => new StackOrQueueConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(object), createObjectWithArgs: null, addFunc: addFunc ?? throw new ArgumentNullException(nameof(addFunc))); /// - /// Creates metadata for types assignable to . + /// Creates serialization metadata for types assignable to . /// /// The generic definition of the type. /// - /// A to create an instance of the list when deserializing. - /// A instance representing the element type. - /// The option to apply to number collection elements. - /// An optimized serialization implementation assuming pre-determined defaults. - /// + /// Provides serialization metadata about the collection type. + /// Serialization metadata for the given type. public static JsonTypeInfo CreateIEnumerableInfo( JsonSerializerOptions options, - Func? createObjectFunc, - JsonTypeInfo elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc) + JsonCollectionInfoValues collectionInfo) where TCollection : IEnumerable => new JsonTypeInfoInternal( options, - createObjectFunc, - () => new IEnumerableConverter(), - elementInfo, - numberHandling, - serializeFunc, - typeof(object)); + collectionInfo, + () => new IEnumerableConverter()); } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs index 20d5b1f..5cf7292 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Converters.cs @@ -82,18 +82,36 @@ namespace System.Text.Json.Serialization.Metadata private static JsonConverter? s_int64Converter; /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonArrayConverter => s_jsonArrayConverter ??= new JsonArrayConverter(); + private static JsonConverter? s_jsonArrayConverter; + + /// /// Returns a instance that converts values. /// public static JsonConverter JsonElementConverter => s_jsonElementConverter ??= new JsonElementConverter(); private static JsonConverter? s_jsonElementConverter; /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonNodeConverter => s_jsonNodeConverter ??= new JsonNodeConverter(); + private static JsonConverter? s_jsonNodeConverter; + + /// /// Returns a instance that converts values. /// public static JsonConverter JsonObjectConverter => s_jsonObjectConverter ??= new JsonObjectConverter(); private static JsonConverter? s_jsonObjectConverter; /// + /// Returns a instance that converts values. + /// + public static JsonConverter JsonValueConverter => s_jsonValueConverter ??= new JsonValueConverter(); + private static JsonConverter? s_jsonValueConverter; + + /// /// Returns a instance that converts values. /// public static JsonConverter ObjectConverter => s_objectConverter ??= new ObjectConverter(); @@ -161,7 +179,7 @@ namespace System.Text.Json.Serialization.Metadata /// Creates a instance that throws . /// /// The generic definition for the type. - /// + /// A instance that throws public static JsonConverter GetUnsupportedTypeConverter() => new UnsupportedTypeConverter(); @@ -170,7 +188,7 @@ namespace System.Text.Json.Serialization.Metadata /// /// The generic definition for the enum type. /// The to use for serialization and deserialization. - /// + /// A instance that converts values. public static JsonConverter GetEnumConverter(JsonSerializerOptions options) where T : struct, Enum => new EnumConverter(EnumConverterOptions.AllowNumbers, options ?? throw new ArgumentNullException(nameof(options))); @@ -179,7 +197,7 @@ namespace System.Text.Json.Serialization.Metadata /// /// The generic definition for the underlying nullable type. /// Serialization metadata for the underlying nullable type. - /// + /// A instance that converts values public static JsonConverter GetNullableConverter(JsonTypeInfo underlyingTypeInfo) where T : struct { if (underlyingTypeInfo == null) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs index f7cd608..e9b0578 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.cs @@ -16,58 +16,39 @@ namespace System.Text.Json.Serialization.Metadata /// /// The type that the converter for the property returns or accepts when converting JSON data. /// The to initialize the metadata with. - /// Whether the CLR member is a property or field. - /// Whether the CLR member is public. - /// Whether the CLR member is a virtual property. - /// The declaring type of the property or field. - /// The info for the property or field's type. - /// A for the property or field, specified by . - /// Provides a mechanism to get the property or field's value. - /// Provides a mechanism to set the property or field's value. - /// Specifies a condition for the property to be ignored. - /// If the property or field is a number, specifies how it should processed when serializing and deserializing. - /// Whether the property was annotated with . - /// Whether the property was annotated with . - /// The CLR name of the property or field. - /// The name to be used when processing the property or field, specified by . + /// Provides serialization metadata about the property or field. /// A instance intialized with the provided metadata. - public static JsonPropertyInfo CreatePropertyInfo( - JsonSerializerOptions options, - bool isProperty, - bool isPublic, - bool isVirtual, - Type declaringType, - JsonTypeInfo propertyTypeInfo, - JsonConverter? converter, - Func? getter, - Action? setter, - JsonIgnoreCondition? ignoreCondition, - bool hasJsonInclude, - bool isExtensionData, - JsonNumberHandling? numberHandling, - string propertyName, - string? jsonPropertyName) + public static JsonPropertyInfo CreatePropertyInfo(JsonSerializerOptions options, JsonPropertyInfoValues 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; @@ -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 jsonPropertyInfo = new JsonPropertyInfo(); - 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 /// A instance representing the type. public static JsonTypeInfo CreateValueInfo(JsonSerializerOptions options, JsonConverter converter) { - JsonTypeInfo info = new JsonTypeInfoInternal(options, ConverterStrategy.Value); + JsonTypeInfo info = new JsonTypeInfoInternal(options); info.PropertyInfoForTypeInfo = CreateJsonPropertyInfoForClassInfo(typeof(T), info, converter, options); return info; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValues.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValuesOfT.cs similarity index 100% rename from src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValues.cs rename to src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonObjectInfoValuesOfT.cs diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs index 71363ca..f60f045 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoOfT.cs @@ -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 converter, - Func? getter, - Action? setter, - JsonIgnoreCondition? ignoreCondition, - bool hasJsonInclude, - bool isExtensionData, - JsonNumberHandling? numberHandling, - string propertyName, - string? jsonPropertyName) + internal void InitializeForSourceGen(JsonSerializerOptions options, JsonPropertyInfoValues 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; + 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 index 0000000..ed7fffe --- /dev/null +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonPropertyInfoValuesOfT.cs @@ -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 +{ + /// + /// Provides serialization metadata about a property or field. + /// + /// The type to convert of the for the property. + public sealed class JsonPropertyInfoValues + { + /// + /// If , indicates that the member is a property, otherwise indicates the member is a field. + /// + public bool IsProperty { get; init; } + + /// + /// Whether the property or field is public. + /// + public bool IsPublic { get; init; } + + /// + /// Whether the property or field is a virtual property. + /// + public bool IsVirtual { get; init; } + + /// + /// The declaring type of the property or field. + /// + public Type DeclaringType { get; init; } = null!; + + /// + /// The info for the property or field's type. + /// + public JsonTypeInfo PropertyTypeInfo { get; init; } = null!; + + /// + /// A for the property or field, specified by . + /// + public JsonConverter? Converter { get; init; } + + /// + /// Provides a mechanism to get the property or field's value. + /// + public Func? Getter { get; init; } + + /// + /// Provides a mechanism to set the property or field's value. + /// + public Action? Setter { get; init; } + + /// + /// Specifies a condition for the member to be ignored. + /// + public JsonIgnoreCondition? IgnoreCondition { get; init; } + + /// + /// Whether the property was annotated with . + /// + public bool HasJsonInclude { get; init; } + + /// + /// Whether the property was annotated with . + /// + public bool IsExtensionData { get; init; } + + /// + /// If the property or field is a number, specifies how it should processed when serializing and deserializing. + /// + public JsonNumberHandling? NumberHandling { get; init; } + + /// + /// The name of the property or field. + /// + public string PropertyName { get; init; } = null!; + + /// + /// The name to be used when processing the property or field, specified by . + /// + public string? JsonPropertyName { get; init; } + } +} diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs index cafba2f..55dd814 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfo.cs @@ -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)); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs index e7e5dc7..552b496 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoInternalOfT.cs @@ -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 : JsonTypeInfo { /// - /// Creates serialization metadata given JsonSerializerOptions and a ConverterStrategy. + /// Creates serialization metadata for a type using a simple converter. /// - public JsonTypeInfoInternal(JsonSerializerOptions options, ConverterStrategy converterStrategy) - : base(typeof(T), options, converterStrategy) + public JsonTypeInfoInternal(JsonSerializerOptions options) + : base(typeof(T), options) { } /// /// Creates serialization metadata for an object. /// - public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues objectInfo) : base(typeof(T), options, ConverterStrategy.Object) + public JsonTypeInfoInternal(JsonSerializerOptions options, JsonObjectInfoValues 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; } /// - /// Creates serialization metadata for a . + /// Creates serialization metadata for a collection. /// public JsonTypeInfoInternal( JsonSerializerOptions options, - Func? createObjectFunc, + JsonCollectionInfoValues collectionInfo, Func> converterCreator, - JsonTypeInfo? elementInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, - Type elementType, object? createObjectWithArgs = null, object? addFunc = null) - : base(typeof(T), options, ConverterStrategy.Enumerable) + : base(typeof(T), options) { - JsonConverter converter = new JsonMetadataServicesConverter(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)); + } - /// - /// Creates serialization metadata for a . - /// - public JsonTypeInfoInternal( - JsonSerializerOptions options, - Func? createObjectFunc, - Func> converterCreator, - JsonTypeInfo? keyInfo, - JsonTypeInfo? valueInfo, - JsonNumberHandling numberHandling, - Action? serializeFunc, - Type keyType, - Type elementType, - object? createObjectWithArgs = null) - : base(typeof(T), options, ConverterStrategy.Dictionary) - { - JsonConverter converter = new JsonMetadataServicesConverter(converterCreator, ConverterStrategy.Dictionary); + ConverterStrategy strategy = collectionInfo.KeyInfo == null ? ConverterStrategy.Enumerable : ConverterStrategy.Dictionary; + JsonConverter converter = new JsonMetadataServicesConverter(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? createObjectFunc) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs index 337fd7c..e09f840 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.cs @@ -15,8 +15,8 @@ namespace System.Text.Json.Serialization.Metadata { private Action? _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 } /// - /// A method that serializes an instance of using + /// Serializes an instance of using /// values specified at design time. /// - public Action? Serialize + /// The writer is not flushed after writing. + public Action? SerializeHandler { get { diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs index 177b42f..2c2ee55 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Dictionary.NonStringKey.cs @@ -665,23 +665,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> DictionaryInt32String => _dictionaryInt32String ??= CreateDictionaryConverter(); private JsonTypeInfo>? _dictionaryInt32String; + protected override JsonSerializerOptions? GeneratedSerializerOptions => null; + private JsonTypeInfo> CreateDictionaryConverter() { JsonTypeInfo keyInfo = JsonMetadataServices.CreateValueInfo(Options, new ConverterForInt32()); JsonTypeInfo valueInfo = JsonMetadataServices.CreateValueInfo(Options, JsonMetadataServices.StringConverter); - return JsonMetadataServices.CreateDictionaryInfo, int, string>( - Options, - createObjectFunc: () => new(), - keyInfo, valueInfo, - numberHandling: default, - serializeFunc: null - ); + JsonCollectionInfoValues> info = new() + { + ObjectCreator = () => new(), + KeyInfo = keyInfo, + ElementInfo = valueInfo, + }; + + return JsonMetadataServices.CreateDictionaryInfo, int, string>(Options, info); } } diff --git a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs index 528ac29..1f1c05c 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs @@ -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 PopulateLargeObject(int size) + { + List orders = new List(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 + { + 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 + { + 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() + } + }, + 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 products = new List(); + 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 { "surface", "pro", "laptop" }, + RelatedImages = new List(), + RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"), + GuaranteeStartsAt = new DateTime(), + GuaranteeEndsAt = new DateTime(), + IsActive = true, + RelatedProducts = new List() + }; + product.SalesInfo.Initialize(); + List reviews = new List(); + 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 { 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; + } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs b/src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs similarity index 65% rename from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs rename to src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs index 2d325ea..20562ef 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/JsonNode/SerializerInteropTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/NodeInteropTests.cs @@ -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 obj = Serialization.Tests.StreamTests.PopulateLargeObject(2); - string expected = JsonSerializer.Serialize(obj); + List obj = JsonTestHelper.PopulateLargeObject(2); + string expected = await JsonSerializerWrapperForString.SerializeWrapper(obj); - JsonArray jArray = JsonSerializer.Deserialize(expected); + JsonArray jArray = await JsonSerializerWrapperForString.DeserializeWrapper(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(json); + poco = await JsonSerializerWrapperForString.DeserializeWrapper(json); Assert.Equal(42, (int)poco.Node); Assert.Equal(43, (int)poco.Array[0]); Assert.Equal(44, (int)poco.Value); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/SampleTestData.OrderPayload.cs b/src/libraries/System.Text.Json/tests/Common/SampleTestData.OrderPayload.cs similarity index 100% rename from src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/SampleTestData.OrderPayload.cs rename to src/libraries/System.Text.Json/tests/Common/SampleTestData.OrderPayload.cs diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs index f78c0a4..682323f 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/ContextClasses.cs @@ -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)) diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs index a74dd32..e204e89 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataAndSerializationContextTests.cs @@ -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); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs index d9fb766..3b9a837 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MetadataContextTests.cs @@ -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(() => MetadataWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.Serialize); - Assert.Throws(() => 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(() => MetadataWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => 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(() => MetadataContext.Default.ClassWithBadCustomConverter.Serialize); - Assert.Throws(() => 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(() => MetadataContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => MetadataContext.Default.StructWithBadCustomConverter.SerializeHandler); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs index 82b8288..ede23fc 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/MixedModeContextTests.cs @@ -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(() => MixedModeContext.Default.ClassWithBadCustomConverter.Serialize); - Assert.Throws(() => 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(() => MixedModeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => MixedModeContext.Default.StructWithBadCustomConverter.SerializeHandler); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs index 8681cc7..520be63 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/RealWorldContextTests.cs @@ -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; public JsonTypeInfo Object => _object ??= JsonMetadataServices.CreateValueInfo(Options, JsonMetadataServices.ObjectConverter); private JsonTypeInfo _objectArray; - public JsonTypeInfo ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo(Options, Object, default, serializeFunc: null); + public JsonTypeInfo ObjectArray => _objectArray ??= JsonMetadataServices.CreateArrayInfo(Options, new JsonCollectionInfoValues { 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 index 0000000..4a27daa --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/NodeInteropTests.cs @@ -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))] + [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))] + [JsonSerializable(typeof(JsonArray))] + [JsonSerializable(typeof(Poco))] + [JsonSerializable(typeof(string))] + internal sealed partial class NodeInteropTestsContext_Default : JsonSerializerContext + { + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs index 639f380..5f4b0dc 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationContextTests.cs @@ -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(() => SerializationContext.Default.ClassWithBadCustomConverter.Serialize); - Assert.Throws(() => 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(() => SerializationContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => 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(() => SerializationWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.Serialize); - Assert.Throws(() => 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(() => SerializationWithPerTypeAttributeContext.Default.ClassWithBadCustomConverter.SerializeHandler); + Assert.Throws(() => SerializationWithPerTypeAttributeContext.Default.StructWithBadCustomConverter.SerializeHandler); } } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs index a086659..2bfb070 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/SerializationLogicTests.cs @@ -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. diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index 71681de..b16e2cc 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -40,10 +40,12 @@ + + @@ -75,6 +77,7 @@ + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs index aeb4c30..515579f 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerApiValidation.cs @@ -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 myDummyTypeInfo = GetTypeInfo(); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs index c25e780..567a277 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/MetadataTests/MetadataTests.Options.cs @@ -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 index 0000000..a424cb8 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/NodeInteropTests.cs @@ -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) { } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs index 35d9610..d7e6e92 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/Stream.WriteTests.cs @@ -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 list = PopulateLargeObject(payloadSize); + List list = JsonTestHelper.PopulateLargeObject(payloadSize); JsonSerializerOptions options = new JsonSerializerOptions { @@ -337,10 +337,10 @@ namespace System.Text.Json.Serialization.Tests int length = ListLength * depthFactor; List[] orders = new List[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[] orders = new List[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 PopulateLargeObject(int size) - { - List orders = new List(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 - { - 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 - { - 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() - } - }, - 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 products = new List(); - 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 { "surface", "pro", "laptop" }, - RelatedImages = new List(), - RelatedVideo = new Uri("http://dotnet.test/link/entries/entry/2"), - GuaranteeStartsAt = new DateTime(), - GuaranteeEndsAt = new DateTime(), - IsActive = true, - RelatedProducts = new List() - }; - product.SalesInfo.Initialize(); - List reviews = new List(); - 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{ 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 diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj index 9311481..475d0b3 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/System.Text.Json.Tests.csproj @@ -44,10 +44,12 @@ + + @@ -88,7 +90,6 @@ - @@ -155,6 +156,7 @@ + @@ -173,7 +175,6 @@ - diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 621abed..5b42461 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -196,6 +196,10 @@ + + + + -- 2.7.4