| File: System\Text\Json\Serialization\JsonSerializerOptions.Converters.cs | Web Access |
| Project: src\runtime\src\libraries\System.Text.Json\src\System.Text.Json.csproj (System.Text.Json) |
// 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.Diagnostics.CodeAnalysis; using System.Text.Json.Reflection; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; namespace System.Text.Json { /// <summary> /// Provides options to be used with <see cref="JsonSerializer"/>. /// </summary> public sealed partial class JsonSerializerOptions { /// <summary> /// The list of custom converters. /// </summary> /// <remarks> /// Once serialization or deserialization occurs, the list cannot be modified. /// </remarks> public IList<JsonConverter> Converters => _converters ??= new(this); /// <summary> /// Gets the list of custom type classifier factories. /// </summary> /// <remarks> /// <para> /// Each <see cref="JsonTypeClassifierFactory"/> in the list is consulted (in declaration order) when /// configuring a union or polymorphic type for which no per-type classifier was set via /// <see cref="JsonUnionAttribute.TypeClassifier"/> or <see cref="JsonPolymorphicAttribute.TypeClassifier"/>. /// The first factory whose /// <see cref="JsonTypeClassifierFactory.CanClassify(JsonTypeClassifierContext)"/> returns <see langword="true"/> /// is used; otherwise the built-in type resolution for that metadata shape applies. /// </para> /// <para> /// Once serialization or deserialization occurs, the list cannot be modified. /// </para> /// </remarks> public IList<JsonTypeClassifierFactory> TypeClassifiers => _typeClassifiers ??= new(this); /// <summary> /// Returns the converter for the specified type. /// </summary> /// <param name="typeToConvert">The type to return a converter for.</param> /// <returns> /// The converter for the given type. /// </returns> /// <exception cref="InvalidOperationException"> /// The configured <see cref="JsonConverter"/> for <paramref name="typeToConvert"/> returned an invalid converter. /// </exception> /// <exception cref="NotSupportedException"> /// There is no compatible <see cref="System.Text.Json.Serialization.JsonConverter"/> /// for <paramref name="typeToConvert"/> or its serializable members. /// </exception> [RequiresUnreferencedCode("Getting a converter for a type may require reflection which depends on unreferenced code.")] [RequiresDynamicCode("Getting a converter for a type may require reflection which depends on runtime code generation.")] public JsonConverter GetConverter(Type typeToConvert) { ArgumentNullException.ThrowIfNull(typeToConvert); if (JsonSerializer.IsReflectionEnabledByDefault) { // Backward compatibility -- root & query the default reflection converters // but do not populate the TypeInfoResolver setting. if (_typeInfoResolver is null) { return DefaultJsonTypeInfoResolver.GetConverterForType(typeToConvert, this); } } return GetConverterInternal(typeToConvert); } /// <summary> /// Same as GetConverter but without defaulting to reflection converters. /// </summary> internal JsonConverter GetConverterInternal(Type typeToConvert) { JsonTypeInfo jsonTypeInfo = GetTypeInfoInternal(typeToConvert, ensureConfigured: false, resolveIfMutable: true); return jsonTypeInfo.Converter; } internal JsonConverter? GetConverterFromList(Type typeToConvert) { if (_converters is { } converterList) { foreach (JsonConverter item in converterList) { if (item.CanConvert(typeToConvert)) { return item; } } } return null; } internal JsonTypeClassifierFactory? GetTypeClassifierFromList(JsonTypeClassifierContext context) { if (_typeClassifiers is { } classifierList) { foreach (JsonTypeClassifierFactory item in classifierList) { if (item.CanClassify(context)) { return item; } } } return null; } [return: NotNullIfNotNull(nameof(converter))] internal JsonConverter? ExpandConverterFactory(JsonConverter? converter, Type typeToConvert) { if (converter is JsonConverterFactory factory) { converter = factory.GetConverterInternal(typeToConvert, this); } return converter; } internal static void CheckConverterNullabilityIsSameAsPropertyType(JsonConverter converter, Type propertyType) { // User has indicated that either: // a) a non-nullable-struct handling converter should handle a nullable struct type or // b) a nullable-struct handling converter should handle a non-nullable struct type. // User should implement a custom converter for the underlying struct and remove the unnecessary CanConvert method override. // The serializer will automatically wrap the custom converter with NullableConverter<T>. // // We also throw to avoid passing an invalid argument to setters for nullable struct properties, // which would cause an InvalidProgramException when the generated IL is invoked. if (propertyType.IsValueType && converter.IsValueType && (propertyType.IsNullableOfT() ^ converter.Type!.IsNullableOfT())) { ThrowHelper.ThrowInvalidOperationException_ConverterCanConvertMultipleTypes(propertyType, converter); } } } }