<PackageReference Include="System.Text.Json" Version="10.0.0-preview.1.25080.5" />

JsonSerializerOptions

public sealed class JsonSerializerOptions
Provides options to be used with JsonSerializer.
using System.Collections.Concurrent; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Text.Encodings.Web; using System.Text.Json.Nodes; using System.Text.Json.Reflection; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; using System.Threading; namespace System.Text.Json { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] [DebuggerDisplay("{DebuggerDisplay,nq}")] public sealed class JsonSerializerOptions { internal sealed class CachingContext { private sealed class CacheEntry { public readonly bool HasResult; public readonly JsonTypeInfo TypeInfo; public readonly ExceptionDispatchInfo ExceptionDispatchInfo; public volatile bool IsNearestAncestorResolved; public CacheEntry NearestAncestor; public CacheEntry(JsonTypeInfo typeInfo) { TypeInfo = typeInfo; HasResult = (typeInfo != null); } public CacheEntry(ExceptionDispatchInfo exception) { ExceptionDispatchInfo = exception; HasResult = true; } public JsonTypeInfo GetResult() { ExceptionDispatchInfo?.Throw(); return TypeInfo; } } private readonly ConcurrentDictionary<Type, CacheEntry> _cache = new ConcurrentDictionary<Type, CacheEntry>(); private readonly Func<Type, CacheEntry> _cacheEntryFactory; public JsonSerializerOptions Options { get; } public int HashCode { get; } public int Count => _cache.Count; public CachingContext(JsonSerializerOptions options, int hashCode) { Options = options; HashCode = hashCode; _cacheEntryFactory = ((Type type) => CreateCacheEntry(type, this)); } public JsonTypeInfo GetOrAddTypeInfo(Type type, bool fallBackToNearestAncestorType = false) { CacheEntry orAddCacheEntry = GetOrAddCacheEntry(type); if (!fallBackToNearestAncestorType || orAddCacheEntry.HasResult) return orAddCacheEntry.GetResult(); return FallBackToNearestAncestor(type, orAddCacheEntry); } public bool TryGetTypeInfo(Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonTypeInfo typeInfo) { _cache.TryGetValue(type, out CacheEntry value); typeInfo = value?.TypeInfo; return typeInfo != null; } public void Clear() { _cache.Clear(); } private CacheEntry GetOrAddCacheEntry(Type type) { return _cache.GetOrAdd(type, _cacheEntryFactory); } private static CacheEntry CreateCacheEntry(Type type, CachingContext context) { try { return new CacheEntry(context.Options.GetTypeInfoNoCaching(type)); } catch (Exception source) { return new CacheEntry(ExceptionDispatchInfo.Capture(source)); } } private JsonTypeInfo FallBackToNearestAncestor(Type type, CacheEntry entry) { return (entry.IsNearestAncestorResolved ? entry.NearestAncestor : DetermineNearestAncestor(type, entry))?.GetResult(); } [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "We only need to examine the interface types that are supported by the underlying resolver.")] private CacheEntry DetermineNearestAncestor(Type type, CacheEntry entry) { CacheEntry cacheEntry = null; Type type2 = null; Type baseType = type.BaseType; while (baseType != (Type)null) { if (baseType == JsonTypeInfo.ObjectType) break; cacheEntry = GetOrAddCacheEntry(baseType); if (cacheEntry.HasResult) { type2 = baseType; break; } baseType = baseType.BaseType; } Type[] interfaces = type.GetInterfaces(); foreach (Type type3 in interfaces) { CacheEntry orAddCacheEntry = GetOrAddCacheEntry(type3); if (orAddCacheEntry.HasResult) { if (type2 != (Type)null) { if (type3.IsAssignableFrom(type2)) continue; if (!type2.IsAssignableFrom(type3)) { cacheEntry = new CacheEntry(ExceptionDispatchInfo.Capture(ThrowHelper.GetNotSupportedException_AmbiguousMetadataForType(type, type2, type3))); break; } } cacheEntry = orAddCacheEntry; type2 = type3; } } entry.NearestAncestor = cacheEntry; entry.IsNearestAncestorResolved = true; return cacheEntry; } } internal static class TrackedCachingContexts { private const int MaxTrackedContexts = 64; private static readonly WeakReference<CachingContext>[] s_trackedContexts = new WeakReference<CachingContext>[64]; private static readonly EqualityComparer s_optionsComparer = new EqualityComparer(); public static CachingContext GetOrCreate(JsonSerializerOptions options) { int hashCode = s_optionsComparer.GetHashCode(options); if (TryGetContext(options, hashCode, out int firstUnpopulatedIndex, out CachingContext result)) return result; if (firstUnpopulatedIndex < 0) return new CachingContext(options, hashCode); lock (s_trackedContexts) { if (!TryGetContext(options, hashCode, out firstUnpopulatedIndex, out result)) { CachingContext cachingContext = new CachingContext(options, hashCode); if (firstUnpopulatedIndex >= 0) { ref WeakReference<CachingContext> reference = ref s_trackedContexts[firstUnpopulatedIndex]; if (reference == null) reference = new WeakReference<CachingContext>(cachingContext); else reference.SetTarget(cachingContext); } return cachingContext; } return result; } } private static bool TryGetContext(JsonSerializerOptions options, int hashCode, out int firstUnpopulatedIndex, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out CachingContext result) { WeakReference<CachingContext>[] array = s_trackedContexts; firstUnpopulatedIndex = -1; for (int i = 0; i < array.Length; i++) { WeakReference<CachingContext> weakReference = array[i]; if (weakReference == null || !weakReference.TryGetTarget(out CachingContext target)) { if (firstUnpopulatedIndex < 0) firstUnpopulatedIndex = i; } else if (hashCode == target.HashCode && s_optionsComparer.Equals(options, target.Options)) { result = target; return true; } } result = null; return false; } } private sealed class EqualityComparer : IEqualityComparer<JsonSerializerOptions> { private struct HashCode { private int _hashCode; public void Add<T>(T value) { _hashCode = (_hashCode, value).GetHashCode(); } public int ToHashCode() { return _hashCode; } } public bool Equals(JsonSerializerOptions left, JsonSerializerOptions right) { if (left._dictionaryKeyPolicy == right._dictionaryKeyPolicy && left._jsonPropertyNamingPolicy == right._jsonPropertyNamingPolicy && left._readCommentHandling == right._readCommentHandling && left._referenceHandler == right._referenceHandler && left._encoder == right._encoder && left._defaultIgnoreCondition == right._defaultIgnoreCondition && left._numberHandling == right._numberHandling && left._preferredObjectCreationHandling == right._preferredObjectCreationHandling && left._unknownTypeHandling == right._unknownTypeHandling && left._unmappedMemberHandling == right._unmappedMemberHandling && left._defaultBufferSize == right._defaultBufferSize && left._maxDepth == right._maxDepth && left.NewLine == right.NewLine && left._allowOutOfOrderMetadataProperties == right._allowOutOfOrderMetadataProperties && left._allowTrailingCommas == right._allowTrailingCommas && left._respectNullableAnnotations == right._respectNullableAnnotations && left._respectRequiredConstructorParameters == right._respectRequiredConstructorParameters && left._ignoreNullValues == right._ignoreNullValues && left._ignoreReadOnlyProperties == right._ignoreReadOnlyProperties && left._ignoreReadonlyFields == right._ignoreReadonlyFields && left._includeFields == right._includeFields && left._propertyNameCaseInsensitive == right._propertyNameCaseInsensitive && left._writeIndented == right._writeIndented && left._indentCharacter == right._indentCharacter && left._indentSize == right._indentSize && left._typeInfoResolver == right._typeInfoResolver) return <Equals>g__CompareLists|0_0(left._converters, right._converters); return false; } public int GetHashCode(JsonSerializerOptions options) { HashCode hc = default(HashCode); <GetHashCode>g__AddHashCode|1_1(ref hc, options._dictionaryKeyPolicy); <GetHashCode>g__AddHashCode|1_1(ref hc, options._jsonPropertyNamingPolicy); <GetHashCode>g__AddHashCode|1_1(ref hc, options._readCommentHandling); <GetHashCode>g__AddHashCode|1_1(ref hc, options._referenceHandler); <GetHashCode>g__AddHashCode|1_1(ref hc, options._encoder); <GetHashCode>g__AddHashCode|1_1(ref hc, options._defaultIgnoreCondition); <GetHashCode>g__AddHashCode|1_1(ref hc, options._numberHandling); <GetHashCode>g__AddHashCode|1_1(ref hc, options._preferredObjectCreationHandling); <GetHashCode>g__AddHashCode|1_1(ref hc, options._unknownTypeHandling); <GetHashCode>g__AddHashCode|1_1(ref hc, options._unmappedMemberHandling); <GetHashCode>g__AddHashCode|1_1(ref hc, options._defaultBufferSize); <GetHashCode>g__AddHashCode|1_1(ref hc, options._maxDepth); <GetHashCode>g__AddHashCode|1_1(ref hc, options.NewLine); <GetHashCode>g__AddHashCode|1_1(ref hc, options._allowOutOfOrderMetadataProperties); <GetHashCode>g__AddHashCode|1_1(ref hc, options._allowTrailingCommas); <GetHashCode>g__AddHashCode|1_1(ref hc, options._respectNullableAnnotations); <GetHashCode>g__AddHashCode|1_1(ref hc, options._respectRequiredConstructorParameters); <GetHashCode>g__AddHashCode|1_1(ref hc, options._ignoreNullValues); <GetHashCode>g__AddHashCode|1_1(ref hc, options._ignoreReadOnlyProperties); <GetHashCode>g__AddHashCode|1_1(ref hc, options._ignoreReadonlyFields); <GetHashCode>g__AddHashCode|1_1(ref hc, options._includeFields); <GetHashCode>g__AddHashCode|1_1(ref hc, options._propertyNameCaseInsensitive); <GetHashCode>g__AddHashCode|1_1(ref hc, options._writeIndented); <GetHashCode>g__AddHashCode|1_1(ref hc, options._indentCharacter); <GetHashCode>g__AddHashCode|1_1(ref hc, options._indentSize); <GetHashCode>g__AddHashCode|1_1(ref hc, options._typeInfoResolver); <GetHashCode>g__AddListHashCode|1_0(ref hc, options._converters); return hc.ToHashCode(); } } internal static class TrackedOptionsInstances { public static ConditionalWeakTable<JsonSerializerOptions, object> All { get; } = new ConditionalWeakTable<JsonSerializerOptions, object>(); } private sealed class ConverterList : ConfigurationList<JsonConverter> { private readonly JsonSerializerOptions _options; public override bool IsReadOnly => _options.IsReadOnly; public ConverterList(JsonSerializerOptions options, IList<JsonConverter> source = null) : base((IEnumerable<JsonConverter>)source) { _options = options; } protected override void OnCollectionModifying() { _options.VerifyMutable(); } } private sealed class OptionsBoundJsonTypeInfoResolverChain : JsonTypeInfoResolverChain { private readonly JsonSerializerOptions _options; public override bool IsReadOnly => _options.IsReadOnly; public OptionsBoundJsonTypeInfoResolverChain(JsonSerializerOptions options) { _options = options; AddFlattened(options._typeInfoResolver); } protected override void ValidateAddedValue(IJsonTypeInfoResolver item) { if (item == this || item == _options._typeInfoResolver) ThrowHelper.ThrowInvalidOperationException_InvalidChainedResolver(); } protected override void OnCollectionModifying() { _options.VerifyMutable(); } protected override void OnCollectionModified() { _options._typeInfoResolver = this; } } private CachingContext _cachingContext; private volatile JsonTypeInfo _lastTypeInfo; private JsonTypeInfo _objectTypeInfo; internal const int BufferSizeDefault = 16384; internal const int DefaultMaxDepth = 64; private static JsonSerializerOptions s_defaultOptions; private static JsonSerializerOptions s_webOptions; private IJsonTypeInfoResolver _typeInfoResolver; private JsonNamingPolicy _dictionaryKeyPolicy; private JsonNamingPolicy _jsonPropertyNamingPolicy; private JsonCommentHandling _readCommentHandling; private ReferenceHandler _referenceHandler; private JavaScriptEncoder _encoder; private ConverterList _converters; private JsonIgnoreCondition _defaultIgnoreCondition; private JsonNumberHandling _numberHandling; private JsonObjectCreationHandling _preferredObjectCreationHandling; private JsonUnknownTypeHandling _unknownTypeHandling; private JsonUnmappedMemberHandling _unmappedMemberHandling; private int _defaultBufferSize = 16384; private int _maxDepth; private bool _allowOutOfOrderMetadataProperties; private bool _allowTrailingCommas; private bool _respectNullableAnnotations = AppContextSwitchHelper.RespectNullableAnnotationsDefault; private bool _respectRequiredConstructorParameters = AppContextSwitchHelper.RespectRequiredConstructorParametersDefault; private bool _ignoreNullValues; private bool _ignoreReadOnlyProperties; private bool _ignoreReadonlyFields; private bool _includeFields; private string _newLine; private bool _propertyNameCaseInsensitive; private bool _writeIndented; private char _indentCharacter = ' '; private int _indentSize = 2; private OptionsBoundJsonTypeInfoResolverChain _typeInfoResolverChain; private bool? _canUseFastPathSerializationLogic; internal JsonKnownReferenceHandler ReferenceHandlingStrategy; private volatile bool _isReadOnly; private volatile bool _isConfiguredForJsonSerializer; private IJsonTypeInfoResolver _effectiveJsonTypeInfoResolver; [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal CachingContext CacheContext { get { return _cachingContext ?? <get_CacheContext>g__GetOrCreate|1_0(); } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal JsonTypeInfo ObjectTypeInfo { get { return _objectTypeInfo ?? (_objectTypeInfo = GetTypeInfoInternal(JsonTypeInfo.ObjectType, true, true, false, false)); } } public IList<JsonConverter> Converters => _converters ?? (_converters = new ConverterList(this, null)); public static JsonSerializerOptions Default { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] get { return s_defaultOptions ?? GetOrCreateSingleton(ref s_defaultOptions, JsonSerializerDefaults.General); } } public static JsonSerializerOptions Web { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] get { return s_webOptions ?? GetOrCreateSingleton(ref s_webOptions, JsonSerializerDefaults.Web); } } [System.Runtime.CompilerServices.Nullable(2)] public IJsonTypeInfoResolver TypeInfoResolver { [System.Runtime.CompilerServices.NullableContext(2)] get { return _typeInfoResolver; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); OptionsBoundJsonTypeInfoResolverChain typeInfoResolverChain = _typeInfoResolverChain; if (typeInfoResolverChain != null && typeInfoResolverChain != value) { typeInfoResolverChain.Clear(); typeInfoResolverChain.AddFlattened(value); } _typeInfoResolver = value; } } public IList<IJsonTypeInfoResolver> TypeInfoResolverChain => _typeInfoResolverChain ?? (_typeInfoResolverChain = new OptionsBoundJsonTypeInfoResolverChain(this)); public bool AllowOutOfOrderMetadataProperties { get { return _allowOutOfOrderMetadataProperties; } set { VerifyMutable(); _allowOutOfOrderMetadataProperties = value; } } public bool AllowTrailingCommas { get { return _allowTrailingCommas; } set { VerifyMutable(); _allowTrailingCommas = value; } } public int DefaultBufferSize { get { return _defaultBufferSize; } set { VerifyMutable(); if (value < 1) throw new ArgumentException(System.SR.SerializationInvalidBufferSize); _defaultBufferSize = value; } } [System.Runtime.CompilerServices.Nullable(2)] public JavaScriptEncoder Encoder { [System.Runtime.CompilerServices.NullableContext(2)] get { return _encoder; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _encoder = value; } } [System.Runtime.CompilerServices.Nullable(2)] public JsonNamingPolicy DictionaryKeyPolicy { [System.Runtime.CompilerServices.NullableContext(2)] get { return _dictionaryKeyPolicy; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _dictionaryKeyPolicy = value; } } [System.Obsolete("JsonSerializerOptions.IgnoreNullValues is obsolete. To ignore null values when serializing, set DefaultIgnoreCondition to JsonIgnoreCondition.WhenWritingNull.", DiagnosticId = "SYSLIB0020", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [EditorBrowsable(EditorBrowsableState.Never)] public bool IgnoreNullValues { get { return _ignoreNullValues; } set { VerifyMutable(); if (value && _defaultIgnoreCondition != 0) throw new InvalidOperationException(System.SR.DefaultIgnoreConditionAlreadySpecified); _ignoreNullValues = value; } } public JsonIgnoreCondition DefaultIgnoreCondition { get { return _defaultIgnoreCondition; } set { VerifyMutable(); switch (value) { case JsonIgnoreCondition.Always: throw new ArgumentException(System.SR.DefaultIgnoreConditionInvalid); default: if (_ignoreNullValues) throw new InvalidOperationException(System.SR.DefaultIgnoreConditionAlreadySpecified); break; case JsonIgnoreCondition.Never: break; } _defaultIgnoreCondition = value; } } public JsonNumberHandling NumberHandling { get { return _numberHandling; } set { VerifyMutable(); if (!JsonSerializer.IsValidNumberHandlingValue(value)) throw new ArgumentOutOfRangeException("value"); _numberHandling = value; } } public JsonObjectCreationHandling PreferredObjectCreationHandling { get { return _preferredObjectCreationHandling; } set { VerifyMutable(); if (!JsonSerializer.IsValidCreationHandlingValue(value)) throw new ArgumentOutOfRangeException("value"); _preferredObjectCreationHandling = value; } } public bool IgnoreReadOnlyProperties { get { return _ignoreReadOnlyProperties; } set { VerifyMutable(); _ignoreReadOnlyProperties = value; } } public bool IgnoreReadOnlyFields { get { return _ignoreReadonlyFields; } set { VerifyMutable(); _ignoreReadonlyFields = value; } } public bool IncludeFields { get { return _includeFields; } set { VerifyMutable(); _includeFields = value; } } public int MaxDepth { get { return _maxDepth; } set { VerifyMutable(); if (value < 0) ThrowHelper.ThrowArgumentOutOfRangeException_MaxDepthMustBePositive("value"); _maxDepth = value; EffectiveMaxDepth = ((value == 0) ? 64 : value); } } internal int EffectiveMaxDepth { get; set; } = 64; [System.Runtime.CompilerServices.Nullable(2)] public JsonNamingPolicy PropertyNamingPolicy { [System.Runtime.CompilerServices.NullableContext(2)] get { return _jsonPropertyNamingPolicy; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _jsonPropertyNamingPolicy = value; } } public bool PropertyNameCaseInsensitive { get { return _propertyNameCaseInsensitive; } set { VerifyMutable(); _propertyNameCaseInsensitive = value; } } public JsonCommentHandling ReadCommentHandling { get { return _readCommentHandling; } set { VerifyMutable(); if ((int)value > 1) throw new ArgumentOutOfRangeException("value", System.SR.JsonSerializerDoesNotSupportComments); _readCommentHandling = value; } } public JsonUnknownTypeHandling UnknownTypeHandling { get { return _unknownTypeHandling; } set { VerifyMutable(); _unknownTypeHandling = value; } } public JsonUnmappedMemberHandling UnmappedMemberHandling { get { return _unmappedMemberHandling; } set { VerifyMutable(); _unmappedMemberHandling = value; } } public bool WriteIndented { get { return _writeIndented; } set { VerifyMutable(); _writeIndented = value; } } public char IndentCharacter { get { return _indentCharacter; } set { JsonWriterHelper.ValidateIndentCharacter(value); VerifyMutable(); _indentCharacter = value; } } public int IndentSize { get { return _indentSize; } set { JsonWriterHelper.ValidateIndentSize(value); VerifyMutable(); _indentSize = value; } } [System.Runtime.CompilerServices.Nullable(2)] public ReferenceHandler ReferenceHandler { [System.Runtime.CompilerServices.NullableContext(2)] get { return _referenceHandler; } [System.Runtime.CompilerServices.NullableContext(2)] set { VerifyMutable(); _referenceHandler = value; ReferenceHandlingStrategy = (value?.HandlingStrategy ?? JsonKnownReferenceHandler.Unspecified); } } public string NewLine { get { return _newLine ?? (_newLine = Environment.NewLine); } set { JsonWriterHelper.ValidateNewLine(value); VerifyMutable(); _newLine = value; } } public bool RespectNullableAnnotations { get { return _respectNullableAnnotations; } set { VerifyMutable(); _respectNullableAnnotations = value; } } public bool RespectRequiredConstructorParameters { get { return _respectRequiredConstructorParameters; } set { VerifyMutable(); _respectRequiredConstructorParameters = value; } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] internal bool CanUseFastPathSerializationLogic { get { bool valueOrDefault = _canUseFastPathSerializationLogic.GetValueOrDefault(); if (!_canUseFastPathSerializationLogic.HasValue) { valueOrDefault = TypeInfoResolver.IsCompatibleWithOptions(this); _canUseFastPathSerializationLogic = valueOrDefault; return valueOrDefault; } return valueOrDefault; } } public bool IsReadOnly => _isReadOnly; [DebuggerBrowsable(DebuggerBrowsableState.Never)] private string DebuggerDisplay { get { return string.Format("TypeInfoResolver = {0}, IsReadOnly = {1}", TypeInfoResolver?.ToString() ?? "<null>", IsReadOnly); } } public JsonTypeInfo GetTypeInfo(Type type) { if ((object)type == null) ThrowHelper.ThrowArgumentNullException("type"); if (JsonTypeInfo.IsInvalidForSerialization(type)) ThrowHelper.ThrowArgumentException_CannotSerializeInvalidType("type", type, null, null); return GetTypeInfoInternal(type, true, true, true, false); } public bool TryGetTypeInfo(Type type, [System.Runtime.CompilerServices.Nullable(2)] [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonTypeInfo typeInfo) { if ((object)type == null) ThrowHelper.ThrowArgumentNullException("type"); if (JsonTypeInfo.IsInvalidForSerialization(type)) ThrowHelper.ThrowArgumentException_CannotSerializeInvalidType("type", type, null, null); typeInfo = GetTypeInfoInternal(type, true, null, true, false); return typeInfo != null; } [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("ensureNotNull")] internal JsonTypeInfo GetTypeInfoInternal(Type type, bool ensureConfigured = true, bool? ensureNotNull = true, bool resolveIfMutable = false, bool fallBackToNearestAncestorType = false) { JsonTypeInfo jsonTypeInfo = null; if (IsReadOnly) { jsonTypeInfo = CacheContext.GetOrAddTypeInfo(type, fallBackToNearestAncestorType); if (ensureConfigured) jsonTypeInfo?.EnsureConfigured(); } else if (resolveIfMutable) { jsonTypeInfo = GetTypeInfoNoCaching(type); } if (jsonTypeInfo == null && ensureNotNull.GetValueOrDefault()) ThrowHelper.ThrowNotSupportedException_NoMetadataForType(type, TypeInfoResolver); return jsonTypeInfo; } internal bool TryGetTypeInfoCached(Type type, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonTypeInfo typeInfo) { if (_cachingContext == null) { typeInfo = null; return false; } return _cachingContext.TryGetTypeInfo(type, out typeInfo); } internal JsonTypeInfo GetTypeInfoForRootType(Type type, bool fallBackToNearestAncestorType = false) { JsonTypeInfo jsonTypeInfo = _lastTypeInfo; if (jsonTypeInfo?.Type != type) { bool fallBackToNearestAncestorType2 = fallBackToNearestAncestorType; jsonTypeInfo = (_lastTypeInfo = GetTypeInfoInternal(type, true, true, false, fallBackToNearestAncestorType2)); } return jsonTypeInfo; } internal bool TryGetPolymorphicTypeInfoForRootType(object rootValue, [System.Diagnostics.CodeAnalysis.NotNullWhen(true)] out JsonTypeInfo polymorphicTypeInfo) { Type type = rootValue.GetType(); if (type != JsonTypeInfo.ObjectType) { polymorphicTypeInfo = GetTypeInfoForRootType(type, true); JsonTypeInfo ancestorPolymorphicType = polymorphicTypeInfo.AncestorPolymorphicType; if (ancestorPolymorphicType != null) polymorphicTypeInfo = ancestorPolymorphicType; return true; } polymorphicTypeInfo = null; return false; } internal void ClearCaches() { _cachingContext?.Clear(); _lastTypeInfo = null; _objectTypeInfo = null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Getting a converter for a type may require reflection which depends on unreferenced code.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Getting a converter for a type may require reflection which depends on runtime code generation.")] public JsonConverter GetConverter(Type typeToConvert) { if ((object)typeToConvert == null) ThrowHelper.ThrowArgumentNullException("typeToConvert"); if (JsonSerializer.IsReflectionEnabledByDefault && _typeInfoResolver == null) return DefaultJsonTypeInfoResolver.GetConverterForType(typeToConvert, this, true); return GetConverterInternal(typeToConvert); } internal JsonConverter GetConverterInternal(Type typeToConvert) { return GetTypeInfoInternal(typeToConvert, false, true, true, false).Converter; } internal JsonConverter GetConverterFromList(Type typeToConvert) { ConverterList converters = _converters; if (converters != null) { foreach (JsonConverter item in converters) { if (item.CanConvert(typeToConvert)) return item; } } return null; } [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("converter")] internal JsonConverter ExpandConverterFactory(JsonConverter converter, Type typeToConvert) { JsonConverterFactory jsonConverterFactory = converter as JsonConverterFactory; if (jsonConverterFactory != null) converter = jsonConverterFactory.GetConverterInternal(typeToConvert, this); return converter; } internal static void CheckConverterNullabilityIsSameAsPropertyType(JsonConverter converter, Type propertyType) { if (propertyType.IsValueType && converter.IsValueType && (propertyType.IsNullableOfT() ^ converter.Type.IsNullableOfT())) ThrowHelper.ThrowInvalidOperationException_ConverterCanConvertMultipleTypes(propertyType, converter); } public JsonSerializerOptions() { TrackOptionsInstance(this); } public JsonSerializerOptions(JsonSerializerOptions options) { if (options == null) ThrowHelper.ThrowArgumentNullException("options"); _dictionaryKeyPolicy = options._dictionaryKeyPolicy; _jsonPropertyNamingPolicy = options._jsonPropertyNamingPolicy; _readCommentHandling = options._readCommentHandling; _referenceHandler = options._referenceHandler; ConverterList converters = options._converters; _converters = ((converters != null) ? new ConverterList(this, converters) : null); _encoder = options._encoder; _defaultIgnoreCondition = options._defaultIgnoreCondition; _numberHandling = options._numberHandling; _preferredObjectCreationHandling = options._preferredObjectCreationHandling; _unknownTypeHandling = options._unknownTypeHandling; _unmappedMemberHandling = options._unmappedMemberHandling; _defaultBufferSize = options._defaultBufferSize; _maxDepth = options._maxDepth; _allowOutOfOrderMetadataProperties = options._allowOutOfOrderMetadataProperties; _allowTrailingCommas = options._allowTrailingCommas; _respectNullableAnnotations = options._respectNullableAnnotations; _respectRequiredConstructorParameters = options._respectRequiredConstructorParameters; _ignoreNullValues = options._ignoreNullValues; _ignoreReadOnlyProperties = options._ignoreReadOnlyProperties; _ignoreReadonlyFields = options._ignoreReadonlyFields; _includeFields = options._includeFields; _newLine = options._newLine; _propertyNameCaseInsensitive = options._propertyNameCaseInsensitive; _writeIndented = options._writeIndented; _indentCharacter = options._indentCharacter; _indentSize = options._indentSize; _typeInfoResolver = options._typeInfoResolver; EffectiveMaxDepth = options.EffectiveMaxDepth; ReferenceHandlingStrategy = options.ReferenceHandlingStrategy; TrackOptionsInstance(this); } public JsonSerializerOptions(JsonSerializerDefaults defaults) : this() { switch (defaults) { case JsonSerializerDefaults.General: break; case JsonSerializerDefaults.Web: _propertyNameCaseInsensitive = true; _jsonPropertyNamingPolicy = JsonNamingPolicy.CamelCase; _numberHandling = JsonNumberHandling.AllowReadingFromString; break; default: throw new ArgumentOutOfRangeException("defaults"); } } private static void TrackOptionsInstance(JsonSerializerOptions options) { TrackedOptionsInstances.All.Add(options, null); } [System.Runtime.CompilerServices.NullableContext(0)] [System.Obsolete("JsonSerializerOptions.AddContext is obsolete. To register a JsonSerializerContext, use either the TypeInfoResolver or TypeInfoResolverChain properties.", DiagnosticId = "SYSLIB0049", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [EditorBrowsable(EditorBrowsableState.Never)] public void AddContext<TContext>() where TContext : JsonSerializerContext, new { VerifyMutable(); new TContext().AssociateWithOptions(this); } public void MakeReadOnly() { if (_typeInfoResolver == null) ThrowHelper.ThrowInvalidOperationException_JsonSerializerOptionsNoTypeInfoResolverSpecified(); _isReadOnly = true; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("Populating unconfigured TypeInfoResolver properties with the reflection resolver requires unreferenced code.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Populating unconfigured TypeInfoResolver properties with the reflection resolver requires runtime code generation.")] public void MakeReadOnly(bool populateMissingResolver) { if (populateMissingResolver) { if (!_isConfiguredForJsonSerializer) ConfigureForJsonSerializer(); } else MakeReadOnly(); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] private void ConfigureForJsonSerializer() { if (JsonSerializer.IsReflectionEnabledByDefault) { DefaultJsonTypeInfoResolver defaultInstance = DefaultJsonTypeInfoResolver.DefaultInstance; IJsonTypeInfoResolver typeInfoResolver = _typeInfoResolver; if (typeInfoResolver != null) { JsonSerializerContext jsonSerializerContext = typeInfoResolver as JsonSerializerContext; if (jsonSerializerContext != null && AppContextSwitchHelper.IsSourceGenReflectionFallbackEnabled) { _effectiveJsonTypeInfoResolver = JsonTypeInfoResolver.Combine(new ReadOnlySpan<IJsonTypeInfoResolver>(new IJsonTypeInfoResolver[2] { jsonSerializerContext, defaultInstance })); CachingContext cachingContext = _cachingContext; if (cachingContext != null) { if (cachingContext.Options != this && !cachingContext.Options._isConfiguredForJsonSerializer) cachingContext.Options.ConfigureForJsonSerializer(); else cachingContext.Clear(); } } } else _typeInfoResolver = defaultInstance; } else { IJsonTypeInfoResolver typeInfoResolver = _typeInfoResolver; if ((typeInfoResolver == null || typeInfoResolver is EmptyJsonTypeInfoResolver) ? true : false) ThrowHelper.ThrowInvalidOperationException_JsonSerializerIsReflectionDisabled(); } _isReadOnly = true; _isConfiguredForJsonSerializer = true; } private JsonTypeInfo GetTypeInfoNoCaching(Type type) { IJsonTypeInfoResolver jsonTypeInfoResolver = _effectiveJsonTypeInfoResolver ?? _typeInfoResolver; if (jsonTypeInfoResolver == null) return null; JsonTypeInfo jsonTypeInfo = jsonTypeInfoResolver.GetTypeInfo(type, this); if (jsonTypeInfo != null) { if (jsonTypeInfo.Type != type) ThrowHelper.ThrowInvalidOperationException_ResolverTypeNotCompatible(type, jsonTypeInfo.Type); if (jsonTypeInfo.Options != this) ThrowHelper.ThrowInvalidOperationException_ResolverTypeInfoOptionsNotCompatible(); } else if (type == JsonTypeInfo.ObjectType) { jsonTypeInfo = new JsonTypeInfo<object>(new SlimObjectConverter(jsonTypeInfoResolver), this); } return jsonTypeInfo; } internal JsonDocumentOptions GetDocumentOptions() { JsonDocumentOptions result = default(JsonDocumentOptions); result.AllowTrailingCommas = AllowTrailingCommas; result.CommentHandling = ReadCommentHandling; result.MaxDepth = MaxDepth; return result; } internal JsonNodeOptions GetNodeOptions() { JsonNodeOptions result = default(JsonNodeOptions); result.PropertyNameCaseInsensitive = PropertyNameCaseInsensitive; return result; } internal JsonReaderOptions GetReaderOptions() { JsonReaderOptions result = default(JsonReaderOptions); result.AllowTrailingCommas = AllowTrailingCommas; result.CommentHandling = ReadCommentHandling; result.MaxDepth = EffectiveMaxDepth; return result; } internal JsonWriterOptions GetWriterOptions() { JsonWriterOptions result = default(JsonWriterOptions); result.Encoder = Encoder; result.Indented = WriteIndented; result.IndentCharacter = IndentCharacter; result.IndentSize = IndentSize; result.MaxDepth = EffectiveMaxDepth; result.NewLine = NewLine; result.SkipValidation = true; return result; } internal void VerifyMutable() { if (_isReadOnly) ThrowHelper.ThrowInvalidOperationException_SerializerOptionsReadOnly(_typeInfoResolver as JsonSerializerContext); } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.")] [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.")] private static JsonSerializerOptions GetOrCreateSingleton(ref JsonSerializerOptions location, JsonSerializerDefaults defaults) { JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(defaults); object typeInfoResolver; if (!JsonSerializer.IsReflectionEnabledByDefault) typeInfoResolver = JsonTypeInfoResolver.Empty; else { IJsonTypeInfoResolver defaultInstance = DefaultJsonTypeInfoResolver.DefaultInstance; typeInfoResolver = defaultInstance; } jsonSerializerOptions.TypeInfoResolver = (IJsonTypeInfoResolver)typeInfoResolver; jsonSerializerOptions._isReadOnly = true; JsonSerializerOptions jsonSerializerOptions2 = jsonSerializerOptions; return Interlocked.CompareExchange(ref location, jsonSerializerOptions2, null) ?? jsonSerializerOptions2; } } }