/// <summary>
/// Specifies that the built-in <see cref="Json.JsonNamingPolicy.CamelCase"/> be used to convert JSON property names.
/// </summary>
- BuiltInCamelCase = 1
+ CamelCase = 1
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+#if !BUILDING_SOURCE_GENERATOR
using System.Text.Json.Serialization.Metadata;
+#endif
namespace System.Text.Json.Serialization
{
/// when serializing and deserializing instances of the specified type and types in its object graph.
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
- public sealed class JsonSerializableAttribute : JsonAttribute
+
+#if BUILDING_SOURCE_GENERATOR
+ internal
+#else
+ public
+#endif
+ sealed class JsonSerializableAttribute : JsonAttribute
{
/// <summary>
/// Initializes a new instance of <see cref="JsonSerializableAttribute"/> with the specified type.
public string? TypeInfoPropertyName { get; set; }
/// <summary>
- /// Determines what the source generator should generate for the type.
+ /// Determines what the source generator should generate for the type. If the value is <see cref="JsonSourceGenerationMode.Default"/>,
+ /// then the setting specified on <see cref="JsonSourceGenerationOptionsAttribute.GenerationMode"/> will be used.
/// </summary>
public JsonSourceGenerationMode GenerationMode { get; set; }
}
enum JsonSourceGenerationMode
{
/// <summary>
- /// Instructs the JSON source generator to generate serialization logic and type metadata to fallback to
- /// when the run-time options are not compatible with the indicated <see cref="JsonSerializerOptionsAttribute"/>.
+ /// When specified on <see cref="JsonSourceGenerationOptionsAttribute.GenerationMode"/>, indicates that both type-metadata initialization logic
+ /// and optimized serialization logic should be generated for all types. When specified on <see cref="JsonSerializableAttribute.GenerationMode"/>,
+ /// indicates that the setting on <see cref="JsonSourceGenerationOptionsAttribute.GenerationMode"/> should be used.
/// </summary>
- /// <remarks>
- /// This mode supports all <see cref="JsonSerializer"/> features.
- /// </remarks>
- MetadataAndSerialization = 0,
+ Default = 0,
/// <summary>
/// Instructs the JSON source generator to generate type-metadata initialization logic.
Metadata = 1,
/// <summary>
- /// Instructs the JSON source generator to generate serialization logic.
+ /// Instructs the JSON source generator to generate optimized serialization logic.
/// </summary>
/// <remarks>
/// This mode supports only a subset of <see cref="JsonSerializer"/> features.
#else
public
#endif
- class JsonSerializerOptionsAttribute : JsonAttribute
+ class JsonSourceGenerationOptionsAttribute : JsonAttribute
{
/// <summary>
/// Specifies the default ignore condition.
/// <summary>
/// Specifies a built-in naming polices to convert JSON property names with.
/// </summary>
- public JsonKnownNamingPolicy NamingPolicy { get; set; }
+ public JsonKnownNamingPolicy PropertyNamingPolicy { get; set; }
/// <summary>
/// Specifies whether JSON output should be pretty-printed.
/// </summary>
public bool WriteIndented { get; set; }
+
+ /// <summary>
+ /// Specifies the source generation mode for types that don't explicitly set the mode with <see cref="JsonSerializableAttribute.GenerationMode"/>.
+ /// </summary>
+ public JsonSourceGenerationMode GenerationMode { get; set; }
}
}
/// </summary>
internal sealed class ContextGenerationSpec
{
- public JsonSerializerOptionsAttribute SerializerOptions { get; init; }
+ public JsonSourceGenerationOptionsAttribute GenerationOptions { get; init; }
public Type ContextType { get; init; }
- public List<TypeGenerationSpec>? RootSerializableTypes { get; init; }
+ public List<TypeGenerationSpec> RootSerializableTypes { get; } = new();
public List<string> ContextClassDeclarationList { get; init; }
bool canBeNull,
List<PropertyGenerationSpec>? properties)
{
- JsonSerializerOptionsAttribute options = _currentContext.SerializerOptions;
+ JsonSourceGenerationOptionsAttribute options = _currentContext.GenerationOptions;
// Add the property names to the context-wide cache; we'll generate the source to initialize them at the end of generation.
- string[] runtimePropNames = GetRuntimePropNames(properties, options.NamingPolicy);
+ string[] runtimePropNames = GetRuntimePropNames(properties, options.PropertyNamingPolicy);
_currentContext.RuntimePropertyNames.UnionWith(runtimePropNames);
StringBuilder sb = new();
{
runtimePropName = jsonPropName;
}
- else if (namingPolicy == JsonKnownNamingPolicy.BuiltInCamelCase)
+ else if (namingPolicy == JsonKnownNamingPolicy.CamelCase)
{
runtimePropName = JsonNamingPolicy.CamelCase.ConvertName(clrPropName);
}
private string WrapWithCheckForCustomConverterIfRequired(string source, string typeCompilableName, string typeFriendlyName, string numberHandlingNamedArg)
{
- if (_currentContext.SerializerOptions.IgnoreRuntimeCustomConverters)
+ if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters)
{
return source;
}
private string GetLogicForDefaultSerializerOptionsInit()
{
- JsonSerializerOptionsAttribute options = _currentContext.SerializerOptions;
+ JsonSourceGenerationOptionsAttribute options = _currentContext.GenerationOptions;
- string? namingPolicyInit = options.NamingPolicy == JsonKnownNamingPolicy.BuiltInCamelCase
+ string? namingPolicyInit = options.PropertyNamingPolicy == JsonKnownNamingPolicy.CamelCase
? $@"
PropertyNamingPolicy = {JsonNamingPolicyTypeRef}.CamelCase"
: null;
private string GetFetchLogicForRuntimeSpecifiedCustomConverter()
{
- if (_currentContext.SerializerOptions.IgnoreRuntimeCustomConverters)
+ if (_currentContext.GenerationOptions.IgnoreRuntimeCustomConverters)
{
return "";
}
Compilation compilation = _executionContext.Compilation;
INamedTypeSymbol jsonSerializerContextSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSerializerContext");
INamedTypeSymbol jsonSerializableAttributeSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSerializableAttribute");
- INamedTypeSymbol jsonSerializerOptionsAttributeSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSerializerOptionsAttribute");
+ INamedTypeSymbol jsonSourceGenerationOptionsAttributeSymbol = compilation.GetTypeByMetadataName("System.Text.Json.Serialization.JsonSourceGenerationOptionsAttribute");
- if (jsonSerializerContextSymbol == null || jsonSerializableAttributeSymbol == null || jsonSerializerOptionsAttributeSymbol == null)
+ if (jsonSerializerContextSymbol == null || jsonSerializableAttributeSymbol == null || jsonSourceGenerationOptionsAttributeSymbol == null)
{
return null;
}
continue;
}
- List<TypeGenerationSpec>? rootTypes = null;
- JsonSerializerOptionsAttribute? options = null;
+ JsonSourceGenerationOptionsAttribute? options = null;
+ List<AttributeSyntax>? serializableAttributeList = null;
foreach (AttributeListSyntax attributeListSyntax in classDeclarationSyntax.AttributeLists)
{
if (jsonSerializableAttributeSymbol.Equals(attributeContainingTypeSymbol, SymbolEqualityComparer.Default))
{
- TypeGenerationSpec? metadata = GetRootSerializableType(compilationSemanticModel, attributeSyntax);
- if (metadata != null)
- {
- (rootTypes ??= new List<TypeGenerationSpec>()).Add(metadata);
- }
+ (serializableAttributeList ??= new List<AttributeSyntax>()).Add(attributeSyntax);
}
- else if (jsonSerializerOptionsAttributeSymbol.Equals(attributeContainingTypeSymbol, SymbolEqualityComparer.Default))
+ else if (jsonSourceGenerationOptionsAttributeSymbol.Equals(attributeContainingTypeSymbol, SymbolEqualityComparer.Default))
{
options = GetSerializerOptions(attributeSyntax);
}
}
- if (rootTypes == null)
+ if (serializableAttributeList == null)
{
// No types were indicated with [JsonSerializable]
continue;
continue;
}
- contextGenSpecList ??= new List<ContextGenerationSpec>();
- contextGenSpecList.Add(new ContextGenerationSpec
+ ContextGenerationSpec contextGenSpec = new()
{
- SerializerOptions = options ?? new JsonSerializerOptionsAttribute(),
+ GenerationOptions = options ?? new JsonSourceGenerationOptionsAttribute(),
ContextType = contextTypeSymbol.AsType(_metadataLoadContext),
- RootSerializableTypes = rootTypes,
ContextClassDeclarationList = classDeclarationList
- });
+ };
+
+ foreach(AttributeSyntax attribute in serializableAttributeList)
+ {
+ TypeGenerationSpec? metadata = GetRootSerializableType(compilationSemanticModel, attribute, contextGenSpec.GenerationOptions.GenerationMode);
+ if (metadata != null)
+ {
+ contextGenSpec.RootSerializableTypes.Add(metadata);
+ }
+ }
+
+ if (contextGenSpec.RootSerializableTypes.Count == 0)
+ {
+ continue;
+ }
+
+ contextGenSpecList ??= new List<ContextGenerationSpec>();
+ contextGenSpecList.Add(contextGenSpec);
// Clear the cache of generated metadata between the processing of context classes.
_typeGenerationSpecCache.Clear();
return match != null;
}
- private static bool TryGetClassDeclarationList(INamedTypeSymbol typeSymbol, [NotNullWhenAttribute(true)] out List<string> classDeclarationList)
+ private static bool TryGetClassDeclarationList(INamedTypeSymbol typeSymbol, [NotNullWhenAttribute(true)] out List<string>? classDeclarationList)
{
- classDeclarationList = new();
-
INamedTypeSymbol currentSymbol = typeSymbol;
+ classDeclarationList = null;
while (currentSymbol != null)
{
declarationElements[tokenCount] = "class";
declarationElements[tokenCount + 1] = currentSymbol.Name;
- classDeclarationList.Add(string.Join(" ", declarationElements));
+ (classDeclarationList ??= new List<string>()).Add(string.Join(" ", declarationElements));
}
currentSymbol = currentSymbol.ContainingType;
return true;
}
- private TypeGenerationSpec? GetRootSerializableType(SemanticModel compilationSemanticModel, AttributeSyntax attributeSyntax)
+ private TypeGenerationSpec? GetRootSerializableType(
+ SemanticModel compilationSemanticModel,
+ AttributeSyntax attributeSyntax,
+ JsonSourceGenerationMode generationMode)
{
IEnumerable<SyntaxNode> attributeArguments = attributeSyntax.DescendantNodes().Where(node => node is AttributeArgumentSyntax);
ITypeSymbol? typeSymbol = null;
string? typeInfoPropertyName = null;
- JsonSourceGenerationMode generationMode = default;
bool seenFirstArg = false;
foreach (AttributeArgumentSyntax node in attributeArguments)
NameEqualsSyntax? propertyNameNode = childNodes.First() as NameEqualsSyntax;
Debug.Assert(propertyNameNode != null);
- SyntaxNode? propertyValueMode = childNodes.ElementAtOrDefault(1);
- if (propertyNameNode.Name.Identifier.ValueText == "TypeInfoPropertyName")
+ SyntaxNode? propertyValueNode = childNodes.ElementAtOrDefault(1);
+ string optionName = propertyNameNode.Name.Identifier.ValueText;
+
+ if (optionName == nameof(JsonSerializableAttribute.TypeInfoPropertyName))
{
- typeInfoPropertyName = propertyValueMode.GetFirstToken().ValueText;
+ typeInfoPropertyName = propertyValueNode.GetFirstToken().ValueText;
}
- else
+ else if (optionName == nameof(JsonSerializableAttribute.GenerationMode))
{
- Debug.Assert(propertyNameNode.Name.Identifier.ValueText == "GenerationMode");
- generationMode = (JsonSourceGenerationMode)Enum.Parse(typeof(JsonSourceGenerationMode), propertyValueMode.GetLastToken().ValueText);
+ JsonSourceGenerationMode? mode = GetJsonSourceGenerationModeEnumVal(propertyValueNode);
+ if (mode.HasValue)
+ {
+ generationMode = mode.Value;
+ }
}
}
}
return null;
}
- TypeGenerationSpec typeGenerationSpec = GetOrAddTypeGenerationSpec(type);
+ TypeGenerationSpec typeGenerationSpec = GetOrAddTypeGenerationSpec(type, generationMode);
if (typeInfoPropertyName != null)
{
typeGenerationSpec.TypeInfoPropertyName = typeInfoPropertyName;
}
- ClassType classType = typeGenerationSpec.ClassType;
- CollectionType collectionType = typeGenerationSpec.CollectionType;
- switch (generationMode)
+ if (generationMode != default)
{
- case JsonSourceGenerationMode.MetadataAndSerialization:
- break;
- case JsonSourceGenerationMode.Metadata:
- typeGenerationSpec.GenerateSerializationLogic = false;
- break;
- case JsonSourceGenerationMode.Serialization:
- typeGenerationSpec.GenerateMetadata = false;
- break;
- default:
- throw new InvalidOperationException();
+ typeGenerationSpec.GenerationMode = generationMode;
}
return typeGenerationSpec;
}
- private static JsonSerializerOptionsAttribute? GetSerializerOptions(AttributeSyntax attributeSyntax)
+ private static JsonSourceGenerationMode? GetJsonSourceGenerationModeEnumVal(SyntaxNode propertyValueMode)
{
+ IEnumerable<string> enumTokens = propertyValueMode
+ .DescendantTokens()
+ .Where(token => IsValidEnumIdentifier(token.ValueText))
+ .Select(token => token.ValueText);
+ string enumAsStr = string.Join(",", enumTokens);
+
+ if (Enum.TryParse<JsonSourceGenerationMode>(enumAsStr, out JsonSourceGenerationMode value))
+ {
+ return value;
+ }
+
+ return null;
+
+ static bool IsValidEnumIdentifier(string token) => token != nameof(JsonSourceGenerationMode) && token != "." && token != "|";
+ }
+
+ private static JsonSourceGenerationOptionsAttribute? GetSerializerOptions(AttributeSyntax? attributeSyntax)
+ {
+ if (attributeSyntax == null)
+ {
+ return null;
+ }
+
IEnumerable<SyntaxNode> attributeArguments = attributeSyntax.DescendantNodes().Where(node => node is AttributeArgumentSyntax);
- JsonSerializerOptionsAttribute options = new();
+ JsonSourceGenerationOptionsAttribute options = new();
foreach (AttributeArgumentSyntax node in attributeArguments)
{
switch (propertyNameNode.Name.Identifier.ValueText)
{
- case "DefaultIgnoreCondition":
- options.DefaultIgnoreCondition = (JsonIgnoreCondition)Enum.Parse(typeof(JsonIgnoreCondition), propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.DefaultIgnoreCondition):
+ {
+ if (Enum.TryParse<JsonIgnoreCondition>(propertyValueStr, out JsonIgnoreCondition value))
+ {
+ options.DefaultIgnoreCondition = value;
+ }
+ }
break;
- case "IgnoreReadOnlyFields":
- options.IgnoreReadOnlyFields = bool.Parse(propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.IgnoreReadOnlyFields):
+ {
+ if (bool.TryParse(propertyValueStr, out bool value))
+ {
+ options.IgnoreReadOnlyFields = value;
+ }
+ }
break;
- case "IgnoreReadOnlyProperties":
- options.IgnoreReadOnlyProperties = bool.Parse(propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.IgnoreReadOnlyProperties):
+ {
+ if (bool.TryParse(propertyValueStr, out bool value))
+ {
+ options.IgnoreReadOnlyProperties = value;
+ }
+ }
+ break;
+ case nameof(JsonSourceGenerationOptionsAttribute.IgnoreRuntimeCustomConverters):
+ {
+ if (bool.TryParse(propertyValueStr, out bool value))
+ {
+ options.IgnoreRuntimeCustomConverters = value;
+ }
+ }
break;
- case "IgnoreRuntimeCustomConverters":
- options.IgnoreRuntimeCustomConverters = bool.Parse(propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.IncludeFields):
+ {
+ if (bool.TryParse(propertyValueStr, out bool value))
+ {
+ options.IncludeFields = value;
+ }
+ }
break;
- case "IncludeFields":
- options.IncludeFields = bool.Parse(propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.PropertyNamingPolicy):
+ {
+ if (Enum.TryParse<JsonKnownNamingPolicy>(propertyValueStr, out JsonKnownNamingPolicy value))
+ {
+ options.PropertyNamingPolicy = value;
+ }
+ }
break;
- case "NamingPolicy":
- options.NamingPolicy = (JsonKnownNamingPolicy)Enum.Parse(typeof(JsonKnownNamingPolicy), propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.WriteIndented):
+ {
+ if (bool.TryParse(propertyValueStr, out bool value))
+ {
+ options.WriteIndented = value;
+ }
+ }
break;
- case "WriteIndented":
- options.WriteIndented = bool.Parse(propertyValueStr);
+ case nameof(JsonSourceGenerationOptionsAttribute.GenerationMode):
+ {
+ JsonSourceGenerationMode? mode = GetJsonSourceGenerationModeEnumVal(propertyValueNode);
+ if (mode.HasValue)
+ {
+ options.GenerationMode = mode.Value;
+ }
+ }
break;
default:
throw new InvalidOperationException();
return options;
}
- private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type)
+ private TypeGenerationSpec GetOrAddTypeGenerationSpec(Type type, JsonSourceGenerationMode generationMode)
{
if (_typeGenerationSpecCache.TryGetValue(type, out TypeGenerationSpec? typeMetadata))
{
foreach (PropertyInfo propertyInfo in currentType.GetProperties(bindingFlags))
{
- PropertyGenerationSpec metadata = GetPropertyGenerationSpec(propertyInfo);
+ PropertyGenerationSpec metadata = GetPropertyGenerationSpec(propertyInfo, generationMode);
// Ignore indexers.
if (propertyInfo.GetIndexParameters().Length > 0)
foreach (FieldInfo fieldInfo in currentType.GetFields(bindingFlags))
{
- PropertyGenerationSpec metadata = GetPropertyGenerationSpec(fieldInfo);
+ PropertyGenerationSpec metadata = GetPropertyGenerationSpec(fieldInfo, generationMode);
if (metadata.CanUseGetter || metadata.CanUseSetter)
{
}
typeMetadata.Initialize(
+ generationMode,
typeRef: type.GetUniqueCompilableTypeName(),
typeInfoPropertyName: type.GetFriendlyTypeName(),
type,
numberHandling,
propertiesMetadata,
collectionType,
- collectionKeyTypeMetadata: collectionKeyType != null ? GetOrAddTypeGenerationSpec(collectionKeyType) : null,
- collectionValueTypeMetadata: collectionValueType != null ? GetOrAddTypeGenerationSpec(collectionValueType) : null,
+ collectionKeyTypeMetadata: collectionKeyType != null ? GetOrAddTypeGenerationSpec(collectionKeyType, generationMode) : null,
+ collectionValueTypeMetadata: collectionValueType != null ? GetOrAddTypeGenerationSpec(collectionValueType, generationMode) : null,
constructionStrategy,
- nullableUnderlyingTypeMetadata: nullableUnderlyingType != null ? GetOrAddTypeGenerationSpec(nullableUnderlyingType) : null,
+ nullableUnderlyingTypeMetadata: nullableUnderlyingType != null ? GetOrAddTypeGenerationSpec(nullableUnderlyingType, generationMode) : null,
converterInstatiationLogic);
return typeMetadata;
}
- private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo)
+ private PropertyGenerationSpec GetPropertyGenerationSpec(MemberInfo memberInfo, JsonSourceGenerationMode generationMode)
{
IList<CustomAttributeData> attributeDataList = CustomAttributeData.GetCustomAttributes(memberInfo);
DefaultIgnoreCondition = ignoreCondition,
NumberHandling = numberHandling,
HasJsonInclude = hasJsonInclude,
- TypeGenerationSpec = GetOrAddTypeGenerationSpec(memberCLRType),
+ TypeGenerationSpec = GetOrAddTypeGenerationSpec(memberCLRType, generationMode),
DeclaringTypeRef = $"global::{memberInfo.DeclaringType.GetUniqueCompilableTypeName()}",
ConverterInstantiationLogic = converterInstantiationLogic
};
/// <param name="executionContext"></param>
public void Execute(GeneratorExecutionContext executionContext)
{
- //if (!Diagnostics.Debugger.IsAttached) { Diagnostics.Debugger.Launch(); };
SyntaxReceiver receiver = (SyntaxReceiver)executionContext.SyntaxReceiver;
List<ClassDeclarationSyntax>? contextClasses = receiver.ClassDeclarationSyntaxList;
if (contextClasses == null)
<Compile Include="..\Common\JsonIgnoreCondition.cs" Link="Common\System\Text\Json\Serialization\JsonIgnoreCondition.cs" />
<Compile Include="..\Common\JsonKnownNamingPolicy.cs" Link="Common\System\Text\Json\Serialization\JsonKnownNamingPolicy.cs" />
<Compile Include="..\Common\JsonNumberHandling.cs" Link="Common\System\Text\Json\Serialization\JsonNumberHandling.cs" />
- <Compile Include="..\Common\JsonSerializerOptionsAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSerializerOptionsAttribute.cs" />
+ <Compile Include="..\Common\JsonSerializableAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSerializableAttribute.cs" />
<Compile Include="..\Common\JsonSourceGenerationMode.cs" Link="Common\System\Text\Json\Serialization\JsonSourceGenerationMode.cs" />
+ <Compile Include="..\Common\JsonSourceGenerationOptionsAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSourceGenerationOptionsAttribute.cs" />
<Compile Include="ClassType.cs" />
<Compile Include="CollectionType.cs" />
<Compile Include="JsonSourceGenerator.cs" />
/// </summary>
public string TypeInfoPropertyName { get; set; }
- public bool GenerateMetadata { get; set; } = true;
+ public JsonSourceGenerationMode GenerationMode { get; set; }
- private bool? _generateSerializationLogic;
- public bool GenerateSerializationLogic
- {
- get => _generateSerializationLogic ??= FastPathIsSupported();
- set => _generateSerializationLogic = value;
- }
+ public bool GenerateMetadata => GenerationModeIsSpecified(JsonSourceGenerationMode.Metadata);
+
+ public bool GenerateSerializationLogic => GenerationModeIsSpecified(JsonSourceGenerationMode.Serialization) && FastPathIsSupported();
public Type Type { get; private set; }
public string? ConverterInstantiationLogic { get; private set; }
public void Initialize(
+ JsonSourceGenerationMode generationMode,
string typeRef,
string typeInfoPropertyName,
Type type,
TypeGenerationSpec? nullableUnderlyingTypeMetadata,
string? converterInstantiationLogic)
{
+ GenerationMode = generationMode;
TypeRef = $"global::{typeRef}";
TypeInfoPropertyName = typeInfoPropertyName;
Type = type;
ConverterInstantiationLogic = converterInstantiationLogic;
}
- public bool FastPathIsSupported()
+ private bool FastPathIsSupported()
{
if (ClassType == ClassType.Object)
{
return false;
}
+
+ private bool GenerationModeIsSpecified(JsonSourceGenerationMode mode) => GenerationMode == JsonSourceGenerationMode.Default || (mode & GenerationMode) != 0;
}
}
public enum JsonKnownNamingPolicy
{
Unspecified = 0,
- BuiltInCamelCase = 1,
+ CamelCase = 1,
}
[System.FlagsAttribute]
public enum JsonNumberHandling
public abstract System.Text.Json.Serialization.Metadata.JsonTypeInfo? GetTypeInfo(System.Type type);
}
[System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false)]
- public partial class JsonSerializerOptionsAttribute : System.Text.Json.Serialization.JsonAttribute
+ public partial class JsonSourceGenerationOptionsAttribute : System.Text.Json.Serialization.JsonAttribute
{
- public JsonSerializerOptionsAttribute() { }
+ public JsonSourceGenerationOptionsAttribute() { }
public System.Text.Json.Serialization.JsonIgnoreCondition DefaultIgnoreCondition { get { throw null; } set { } }
public bool IgnoreReadOnlyFields { get { throw null; } set { } }
public bool IgnoreReadOnlyProperties { get { throw null; } set { } }
public bool IgnoreRuntimeCustomConverters { get { throw null; } set { } }
public bool IncludeFields { get { throw null; } set { } }
- public System.Text.Json.Serialization.JsonKnownNamingPolicy NamingPolicy { 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 { } }
}
[System.FlagsAttribute]
public enum JsonSourceGenerationMode
{
- MetadataAndSerialization = 0,
+ Default = 0,
Metadata = 1,
Serialization = 2,
}
<Compile Include="..\Common\JsonIgnoreCondition.cs" Link="Common\System\Text\Json\Serialization\JsonIgnoreCondition.cs" />
<Compile Include="..\Common\JsonKnownNamingPolicy.cs" Link="Common\System\Text\Json\Serialization\JsonKnownNamingPolicy.cs" />
<Compile Include="..\Common\JsonNumberHandling.cs" Link="Common\System\Text\Json\Serialization\JsonNumberHandling.cs" />
- <Compile Include="..\Common\JsonSerializerOptionsAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSerializerOptionsAttribute.cs" />
+ <Compile Include="..\Common\JsonSerializableAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSerializableAttribute.cs" />
<Compile Include="..\Common\JsonSourceGenerationMode.cs" Link="Common\System\Text\Json\Serialization\JsonSourceGenerationMode.cs" />
+ <Compile Include="..\Common\JsonSourceGenerationOptionsAttribute.cs" Link="Common\System\Text\Json\Serialization\JsonSourceGenerationOptionsAttribute.cs" />
<Compile Include="System\Text\Json\BitStack.cs" />
<Compile Include="System\Text\Json\Document\JsonDocument.cs" />
<Compile Include="System\Text\Json\Document\JsonDocument.DbRow.cs" />
<Compile Include="System\Text\Json\Serialization\Attributes\JsonIncludeAttribute.cs" />
<Compile Include="System\Text\Json\Serialization\Attributes\JsonNumberHandlingAttribute.cs" />
<Compile Include="System\Text\Json\Serialization\Attributes\JsonPropertyNameAttribute.cs" />
- <Compile Include="System\Text\Json\Serialization\Attributes\JsonSerializableAttribute.cs" />
<Compile Include="System\Text\Json\Serialization\Converters\JsonMetadataServicesConverter.cs" />
<Compile Include="System\Text\Json\Serialization\IgnoreReferenceResolver.cs" />
<Compile Include="System\Text\Json\Serialization\JsonSerializerContext.cs" />
/// Creates an instance of <see cref="JsonSerializerContext"/> and binds it with the indicated <see cref="JsonSerializerOptions"/>.
/// </summary>
/// <param name="instanceOptions">The run-time provided options for the context instance.</param>
- /// <param name="defaultOptions">The default run-time options for the context. It's values are defined at design-time via <see cref="JsonSerializerOptionsAttribute"/>.</param>
+ /// <param name="defaultOptions">The default run-time options for the context. It's values are defined at design-time via <see cref="JsonSourceGenerationOptionsAttribute"/>.</param>
/// <remarks>
/// If no instance options are passed, then no options are set until the context is bound using <see cref="JsonSerializerOptions.AddContext{TContext}"/>,
/// or until <see cref="Options"/> is called, where a new options instance is created and bound.
/// <param name="options">The <see cref="JsonSerializerOptions"/> to use.</param>
/// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
/// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
- /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSerializerOptionsAttribute"/> defaults.</param>
+ /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
/// <returns></returns>
public static JsonTypeInfo<TElement[]> CreateArrayInfo<TElement>(
JsonSerializerOptions options,
/// <param name="createObjectFunc">A <see cref="Func{TResult}"/> to create an instance of the list when deserializing.</param>
/// <param name="elementInfo">A <see cref="JsonTypeInfo"/> instance representing the element type.</param>
/// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
- /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSerializerOptionsAttribute"/> defaults.</param>
+ /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
/// <returns></returns>
public static JsonTypeInfo<TCollection> CreateListInfo<TCollection, TElement>(
JsonSerializerOptions options,
/// <param name="keyInfo">A <see cref="JsonTypeInfo"/> instance representing the key type.</param>
/// <param name="valueInfo">A <see cref="JsonTypeInfo"/> instance representing the value type.</param>
/// <param name="numberHandling">The <see cref="JsonNumberHandling"/> option to apply to number collection elements.</param>
- /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSerializerOptionsAttribute"/> defaults.</param>
+ /// <param name="serializeFunc">An optimized serialization implementation assuming pre-determined <see cref="JsonSourceGenerationOptionsAttribute"/> defaults.</param>
/// <returns></returns>
public static JsonTypeInfo<TCollection> CreateDictionaryInfo<TCollection, TKey, TValue>(
JsonSerializerOptions options,
/// <param name="options">The <see cref="JsonSerializerOptions"/> to initialize the metadata with.</param>
/// <param name="createObjectFunc">Provides a mechanism to create an instance of the class or struct when deserializing.</param>
/// <param name="propInitFunc">Provides a mechanism to initialize metadata for properties and fields of the class or struct.</param>
- /// <param name="serializeFunc">Provides a serialization implementation for instances of the class or struct which assumes options specified by <see cref="JsonSerializerOptionsAttribute"/>.</param>
+ /// <param name="serializeFunc">Provides a serialization implementation for instances of the class or struct which assumes options specified by <see cref="JsonSourceGenerationOptionsAttribute"/>.</param>
/// <param name="numberHandling">Specifies how number properties and fields should be processed when serializing and deserializing.</param>
/// <typeparam name="T">The type of the class or struct.</typeparam>
/// <exception cref="InvalidOperationException">Thrown when <paramref name="options"/> and <paramref name="propInitFunc"/> are both null.</exception>
/// <summary>
/// A method that serializes an instance of <typeparamref name="T"/> using
- /// <see cref="JsonSerializerOptionsAttribute"/> values specified at design time.
+ /// <see cref="JsonSourceGenerationOptionsAttribute"/> values specified at design time.
/// </summary>
public Action<Utf8JsonWriter, T>? Serialize { get; private protected set; }
}
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata)]
+ internal partial class MetadataWithPerTypeAttributeContext : JsonSerializerContext, ITestContext
+ {
+ }
+
+ public sealed class MetadataWithPerTypeAttributeContextTests : RealWorldContextTests
+ {
+ public MetadataWithPerTypeAttributeContextTests() : base(MetadataWithPerTypeAttributeContext.Default, (options) => new MetadataWithPerTypeAttributeContext(options)) { }
+
+ [Fact]
+ public override void EnsureFastPathGeneratedAsExpected()
+ {
+ Assert.Null(MetadataWithPerTypeAttributeContext.Default.Location.Serialize);
+ Assert.Null(MetadataWithPerTypeAttributeContext.Default.RepeatedLocation.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.String.Serialize);
+ Assert.Null(MetadataWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
+ }
+ }
+
+ [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)]
+ [JsonSerializable(typeof(Location))]
+ [JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation")]
+ [JsonSerializable(typeof(ActiveOrUpcomingEvent))]
+ [JsonSerializable(typeof(CampaignSummaryViewModel))]
+ [JsonSerializable(typeof(IndexViewModel))]
+ [JsonSerializable(typeof(WeatherForecastWithPOCOs))]
+ [JsonSerializable(typeof(EmptyPoco))]
+ [JsonSerializable(typeof(HighLowTemps))]
+ [JsonSerializable(typeof(MyType))]
+ [JsonSerializable(typeof(MyType2))]
+ [JsonSerializable(typeof(MyIntermediateType))]
+ [JsonSerializable(typeof(HighLowTempsImmutable))]
+ [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))]
+ [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))]
+ [JsonSerializable(typeof(object[]))]
+ [JsonSerializable(typeof(string))]
+ [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))]
internal partial class MetadataContext : JsonSerializerContext, ITestContext
{
}
[JsonSerializable(typeof(WeatherForecastWithPOCOs), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(EmptyPoco), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(HighLowTemps), GenerationMode = JsonSourceGenerationMode.Serialization)]
- [JsonSerializable(typeof(MyType), GenerationMode = JsonSourceGenerationMode.MetadataAndSerialization)]
- [JsonSerializable(typeof(MyType2), GenerationMode = JsonSourceGenerationMode.MetadataAndSerialization)]
- [JsonSerializable(typeof(MyIntermediateType), GenerationMode = JsonSourceGenerationMode.MetadataAndSerialization)]
+ [JsonSerializable(typeof(MyType), GenerationMode = JsonSourceGenerationMode.Default)]
+ [JsonSerializable(typeof(MyType2), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof(MyIntermediateType), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(HighLowTempsImmutable), GenerationMode = JsonSourceGenerationMode.Metadata)]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Metadata)]
- [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.MetadataAndSerialization)]
- [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.MetadataAndSerialization)]
+ [JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)]
internal partial class MixedModeContext : JsonSerializerContext, ITestContext
{
}
string json = JsonSerializer.Serialize(expected, DefaultContext.IndexViewModel);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.IndexViewModel), typeof(CampaignSummaryViewModel));
- IndexViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).IndexViewModel);
+ IndexViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).IndexViewModel);
VerifyIndexViewModel(expected, obj);
}
string json = JsonSerializer.Serialize(expected, DefaultContext.CampaignSummaryViewModel);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.CampaignSummaryViewModel), typeof(CampaignSummaryViewModel));
- CampaignSummaryViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).CampaignSummaryViewModel);
+ CampaignSummaryViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).CampaignSummaryViewModel);
VerifyCampaignSummaryViewModel(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.CampaignSummaryViewModel);
string json = JsonSerializer.Serialize(expected, DefaultContext.WeatherForecastWithPOCOs);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.WeatherForecastWithPOCOs), typeof(HighLowTemps));
- WeatherForecastWithPOCOs obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).WeatherForecastWithPOCOs);
+ WeatherForecastWithPOCOs obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).WeatherForecastWithPOCOs);
VerifyWeatherForecastWithPOCOs(expected, obj);
}
string json = JsonSerializer.Serialize(expected, DefaultContext.EmptyPoco);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.EmptyPoco), typeof(EmptyPoco));
- EmptyPoco obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).EmptyPoco);
+ EmptyPoco obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).EmptyPoco);
VerifyEmptyPoco(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.EmptyPoco);
string json = JsonSerializer.Serialize(expected, DefaultContext.RepeatedLocation);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.RepeatedLocation), typeof(RepeatedTypes.Location));
- RepeatedTypes.Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).RepeatedLocation);
+ RepeatedTypes.Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).RepeatedLocation);
VerifyRepeatedLocation(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.RepeatedLocation);
public override void HandlesNestedTypes()
{
string json = @"{""MyInt"":5}";
- MyNestedClass obj = JsonSerializer.Deserialize<MyNestedClass>(json, ((ITestContext)MetadataContext.Default).MyNestedClass);
+ MyNestedClass obj = JsonSerializer.Deserialize<MyNestedClass>(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyNestedClass);
Assert.Equal(5, obj.MyInt);
Assert.Equal(json, JsonSerializer.Serialize(obj, DefaultContext.MyNestedClass));
- MyNestedClass.MyNestedNestedClass obj2 = JsonSerializer.Deserialize<MyNestedClass.MyNestedNestedClass>(json, ((ITestContext)MetadataContext.Default).MyNestedNestedClass);
+ MyNestedClass.MyNestedNestedClass obj2 = JsonSerializer.Deserialize<MyNestedClass.MyNestedNestedClass>(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyNestedNestedClass);
Assert.Equal(5, obj2.MyInt);
Assert.Equal(json, JsonSerializer.Serialize(obj2, DefaultContext.MyNestedNestedClass));
}
CampaignSummaryViewModel campaignSummary = CreateCampaignSummaryViewModel();
string json = JsonSerializer.Serialize(new object[] { index, campaignSummary }, DefaultContext.ObjectArray);
- object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ObjectArray);
+ object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ObjectArray);
JsonElement indexAsJsonElement = (JsonElement)arr[0];
JsonElement campaignSummeryAsJsonElement = (JsonElement)arr[1];
- VerifyIndexViewModel(index, JsonSerializer.Deserialize(indexAsJsonElement.GetRawText(), ((ITestContext)MetadataContext.Default).IndexViewModel));
- VerifyCampaignSummaryViewModel(campaignSummary, JsonSerializer.Deserialize(campaignSummeryAsJsonElement.GetRawText(), ((ITestContext)MetadataContext.Default).CampaignSummaryViewModel));
+ VerifyIndexViewModel(index, JsonSerializer.Deserialize(indexAsJsonElement.GetRawText(), ((ITestContext)MetadataWithPerTypeAttributeContext.Default).IndexViewModel));
+ VerifyCampaignSummaryViewModel(campaignSummary, JsonSerializer.Deserialize(campaignSummeryAsJsonElement.GetRawText(), ((ITestContext)MetadataWithPerTypeAttributeContext.Default).CampaignSummaryViewModel));
}
[Fact]
Assert.Same(JsonNamingPolicy.CamelCase, ((JsonSerializerContext)context).Options.PropertyNamingPolicy);
string json = JsonSerializer.Serialize(new object[] { index, campaignSummary }, context.ObjectArray);
- object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ObjectArray);
+ object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ObjectArray);
JsonElement indexAsJsonElement = (JsonElement)arr[0];
JsonElement campaignSummeryAsJsonElement = (JsonElement)arr[1];
namespace System.Text.Json.SourceGeneration.Tests
{
+ [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Serialization)]
+ [JsonSerializable(typeof(Location))]
+ [JsonSerializable(typeof(RepeatedTypes.Location), TypeInfoPropertyName = "RepeatedLocation")]
+ [JsonSerializable(typeof(ActiveOrUpcomingEvent))]
+ [JsonSerializable(typeof(CampaignSummaryViewModel))]
+ [JsonSerializable(typeof(IndexViewModel))]
+ [JsonSerializable(typeof(WeatherForecastWithPOCOs))]
+ [JsonSerializable(typeof(EmptyPoco))]
+ [JsonSerializable(typeof(HighLowTemps))]
+ [JsonSerializable(typeof(MyType))]
+ [JsonSerializable(typeof(MyType2))]
+ [JsonSerializable(typeof(MyIntermediateType))]
+ [JsonSerializable(typeof(HighLowTempsImmutable))]
+ [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass))]
+ [JsonSerializable(typeof(RealWorldContextTests.MyNestedClass.MyNestedNestedClass))]
+ [JsonSerializable(typeof(object[]))]
+ [JsonSerializable(typeof(string))]
+ [JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable))]
+ internal partial class SerializationContext : JsonSerializerContext, ITestContext
+ {
+ }
+
[JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RepeatedTypes.Location), GenerationMode = JsonSourceGenerationMode.Serialization, TypeInfoPropertyName = "RepeatedLocation")]
[JsonSerializable(typeof(ActiveOrUpcomingEvent), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(object[]), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(string), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RealWorldContextTests.ClassWithEnumAndNullable), GenerationMode = JsonSourceGenerationMode.Serialization)]
- internal partial class SerializationContext : JsonSerializerContext, ITestContext
+ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializerContext, ITestContext
{
}
- [JsonSerializerOptions(NamingPolicy = JsonKnownNamingPolicy.BuiltInCamelCase)]
+ [JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(Location), GenerationMode = JsonSourceGenerationMode.Serialization)]
[JsonSerializable(typeof(RepeatedTypes.Location), GenerationMode = JsonSourceGenerationMode.Serialization, TypeInfoPropertyName = "RepeatedLocation")]
[JsonSerializable(typeof(ActiveOrUpcomingEvent), GenerationMode = JsonSourceGenerationMode.Serialization)]
{
}
- public sealed class SerializationContextTests : RealWorldContextTests
+ public class SerializationContextTests : RealWorldContextTests
{
- public SerializationContextTests() : base(SerializationContext.Default, (options) => new SerializationContext(options)) { }
+ public SerializationContextTests() : this(SerializationContext.Default, (options) => new SerializationContext(options)) { }
+
+ internal SerializationContextTests(ITestContext defaultContext, Func<JsonSerializerOptions, ITestContext> contextCreator)
+ : base(defaultContext, contextCreator)
+ {
+ }
[Fact]
public override void EnsureFastPathGeneratedAsExpected()
string json = JsonSerializer.Serialize(expected, DefaultContext.Location);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.Location), typeof(Location));
- Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).Location);
+ Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).Location);
VerifyLocation(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.Location);
string json = JsonSerializer.Serialize(expected, DefaultContext.IndexViewModel);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.IndexViewModel), typeof(IndexViewModel));
- IndexViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).IndexViewModel);
+ IndexViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).IndexViewModel);
VerifyIndexViewModel(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.IndexViewModel);
string json = JsonSerializer.Serialize(expected, DefaultContext.CampaignSummaryViewModel);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.CampaignSummaryViewModel), typeof(CampaignSummaryViewModel));
- CampaignSummaryViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).CampaignSummaryViewModel);
+ CampaignSummaryViewModel obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).CampaignSummaryViewModel);
VerifyCampaignSummaryViewModel(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.CampaignSummaryViewModel);
string json = JsonSerializer.Serialize(expected, DefaultContext.ActiveOrUpcomingEvent);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.ActiveOrUpcomingEvent), typeof(ActiveOrUpcomingEvent));
- ActiveOrUpcomingEvent obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ActiveOrUpcomingEvent);
+ ActiveOrUpcomingEvent obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ActiveOrUpcomingEvent);
VerifyActiveOrUpcomingEvent(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.ActiveOrUpcomingEvent);
string json = JsonSerializer.Serialize(expected, DefaultContext.WeatherForecastWithPOCOs);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.WeatherForecastWithPOCOs), typeof(WeatherForecastWithPOCOs));
- WeatherForecastWithPOCOs obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).WeatherForecastWithPOCOs);
+ WeatherForecastWithPOCOs obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).WeatherForecastWithPOCOs);
VerifyWeatherForecastWithPOCOs(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.WeatherForecastWithPOCOs);
string json = JsonSerializer.Serialize(expected, DefaultContext.EmptyPoco);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.EmptyPoco), typeof(EmptyPoco));
- EmptyPoco obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).EmptyPoco);
+ EmptyPoco obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).EmptyPoco);
VerifyEmptyPoco(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.EmptyPoco);
string json = JsonSerializer.Serialize(expected, DefaultContext.RepeatedLocation);
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.RepeatedLocation), typeof(RepeatedTypes.Location));
- RepeatedTypes.Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).RepeatedLocation);
+ RepeatedTypes.Location obj = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).RepeatedLocation);
VerifyRepeatedLocation(expected, obj);
AssertFastPathLogicCorrect(json, obj, DefaultContext.RepeatedLocation);
{
MyType myType = new() { Type = new() };
string json = JsonSerializer.Serialize(myType, DefaultContext.MyType);
- myType = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).MyType);
+ myType = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyType);
AssertFastPathLogicCorrect(json, myType, DefaultContext.MyType);
MyType2 myType2 = new() { Type = new MyIntermediateType() { Type = myType } };
json = JsonSerializer.Serialize(myType2, DefaultContext.MyType2);
- myType2 = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).MyType2);
+ myType2 = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyType2);
AssertFastPathLogicCorrect(json, myType2, DefaultContext.MyType2);
}
CampaignSummaryViewModel campaignSummary = CreateCampaignSummaryViewModel();
string json = JsonSerializer.Serialize(new object[] { index, campaignSummary }, DefaultContext.ObjectArray);
- object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ObjectArray);
+ object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ObjectArray);
JsonElement indexAsJsonElement = (JsonElement)arr[0];
JsonElement campaignSummeryAsJsonElement = (JsonElement)arr[1];
- VerifyIndexViewModel(index, JsonSerializer.Deserialize(indexAsJsonElement.GetRawText(), ((ITestContext)MetadataContext.Default).IndexViewModel));
- VerifyCampaignSummaryViewModel(campaignSummary, JsonSerializer.Deserialize(campaignSummeryAsJsonElement.GetRawText(), ((ITestContext)MetadataContext.Default).CampaignSummaryViewModel));
+ VerifyIndexViewModel(index, JsonSerializer.Deserialize(indexAsJsonElement.GetRawText(), ((ITestContext)MetadataWithPerTypeAttributeContext.Default).IndexViewModel));
+ VerifyCampaignSummaryViewModel(campaignSummary, JsonSerializer.Deserialize(campaignSummeryAsJsonElement.GetRawText(), ((ITestContext)MetadataWithPerTypeAttributeContext.Default).CampaignSummaryViewModel));
}
[Fact]
Assert.Contains("description", json);
Assert.Contains("organizationName", json);
- object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ObjectArray);
+ object[] arr = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ObjectArray);
JsonElement indexAsJsonElement = (JsonElement)arr[0];
JsonElement campaignSummeryAsJsonElement = (JsonElement)arr[1];
ITestContext context = new SerializationContext(options);
string json = JsonSerializer.Serialize(new object[] { "Hello", "World" }, typeof(object[]), (JsonSerializerContext)context);
- object[] arr = (object[])JsonSerializer.Deserialize(json, typeof(object[]), (JsonSerializerContext)((ITestContext)MetadataContext.Default));
+ object[] arr = (object[])JsonSerializer.Deserialize(json, typeof(object[]), (JsonSerializerContext)((ITestContext)MetadataWithPerTypeAttributeContext.Default));
JsonElement hello = (JsonElement)arr[0];
JsonElement world = (JsonElement)arr[1];
public override void HandlesNestedTypes()
{
string json = @"{""MyInt"":5}";
- MyNestedClass obj = JsonSerializer.Deserialize<MyNestedClass>(json, ((ITestContext)MetadataContext.Default).MyNestedClass);
+ MyNestedClass obj = JsonSerializer.Deserialize<MyNestedClass>(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyNestedClass);
Assert.Equal(5, obj.MyInt);
Assert.Equal(json, JsonSerializer.Serialize(obj, DefaultContext.MyNestedClass));
- MyNestedClass.MyNestedNestedClass obj2 = JsonSerializer.Deserialize<MyNestedClass.MyNestedNestedClass>(json, ((ITestContext)MetadataContext.Default).MyNestedNestedClass);
+ MyNestedClass.MyNestedNestedClass obj2 = JsonSerializer.Deserialize<MyNestedClass.MyNestedNestedClass>(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).MyNestedNestedClass);
Assert.Equal(5, obj2.MyInt);
Assert.Equal(json, JsonSerializer.Serialize(obj2, DefaultContext.MyNestedNestedClass));
}
void RunTest(ClassWithEnumAndNullable expected)
{
string json = JsonSerializer.Serialize(expected, DefaultContext.ClassWithEnumAndNullable);
- ClassWithEnumAndNullable actual = JsonSerializer.Deserialize(json, ((ITestContext)MetadataContext.Default).ClassWithEnumAndNullable);
+ ClassWithEnumAndNullable actual = JsonSerializer.Deserialize(json, ((ITestContext)MetadataWithPerTypeAttributeContext.Default).ClassWithEnumAndNullable);
Assert.Equal(expected.Day, actual.Day);
Assert.Equal(expected.NullableDay, actual.NullableDay);
}
JsonTestHelper.AssertThrows_PropMetadataInit(() => JsonSerializer.Deserialize(json, DefaultContext.HighLowTempsImmutable), typeof(HighLowTempsImmutable));
}
}
+
+ public sealed class SerializationWithPerTypeAttributeContextTests : SerializationContextTests
+ {
+ public SerializationWithPerTypeAttributeContextTests() : base(SerializationWithPerTypeAttributeContext.Default, (options) => new SerializationContext(options)) { }
+
+ [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.String.Serialize);
+ Assert.NotNull(SerializationWithPerTypeAttributeContext.Default.ClassWithEnumAndNullable.Serialize);
+ }
+ }
}