<PackageReference Include="System.Text.Json" Version="6.0.7" />

JsonConverter<T>

public abstract class JsonConverter<T> : JsonConverter
Converts an object or value to or from JSON.
using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; namespace System.Text.Json.Serialization { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] public abstract class JsonConverter<[System.Runtime.CompilerServices.Nullable(2)] T> : JsonConverter { internal override ConverterStrategy ConverterStrategy => ConverterStrategy.Value; [System.Runtime.CompilerServices.Nullable(2)] internal override Type KeyType { get { return null; } } [System.Runtime.CompilerServices.Nullable(2)] internal override Type ElementType { get { return null; } } public virtual bool HandleNull { get { HandleNullOnRead = !CanBeNull; HandleNullOnWrite = false; return false; } } internal bool HandleNullOnRead { get; set; } internal bool HandleNullOnWrite { get; set; } internal bool CanBeNull { get; } internal sealed override Type TypeToConvert => typeof(T); internal sealed override object ReadCoreAsObject(ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state) { return ReadCore(ref reader, options, ref state); } internal T ReadCore(ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state) { try { if (!state.IsContinuation) { if (!JsonConverter.SingleValueReadWithReadAhead(ConverterStrategy, ref reader, ref state)) { if (!state.SupportContinuation) { state.BytesConsumed += reader.BytesConsumed; return default(T); } state.BytesConsumed += reader.BytesConsumed; if (state.Current.ReturnValue != null) return (T)state.Current.ReturnValue; return default(T); } } else if (!JsonConverter.SingleValueReadWithReadAhead(ConverterStrategy.Value, ref reader, ref state)) { state.BytesConsumed += reader.BytesConsumed; return default(T); } JsonPropertyInfo propertyInfoForTypeInfo = state.Current.JsonTypeInfo.PropertyInfoForTypeInfo; if (TryRead(ref reader, propertyInfoForTypeInfo.RuntimePropertyType, options, ref state, out T value) && !reader.Read() && !reader.IsFinalBlock) state.Current.ReturnValue = value; state.BytesConsumed += reader.BytesConsumed; return value; } catch (JsonReaderException ex) { ThrowHelper.ReThrowWithPath(ref state, ex); return default(T); } catch (FormatException ex2) when (ex2.Source == "System.Text.Json.Rethrowable") { ThrowHelper.ReThrowWithPath(ref state, ref reader, ex2); return default(T); } catch (InvalidOperationException ex3) when (ex3.Source == "System.Text.Json.Rethrowable") { ThrowHelper.ReThrowWithPath(ref state, ref reader, ex3); return default(T); } catch (JsonException ex4) when (ex4.Path == null) { ThrowHelper.AddJsonExceptionInformation(ref state, ref reader, ex4); throw; } catch (NotSupportedException ex5) { if (ex5.Message.Contains(" Path: ")) throw; ThrowHelper.ThrowNotSupportedException(ref state, ref reader, ex5); return default(T); } } internal sealed override bool WriteCoreAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, ref WriteStack state) { if (base.IsValueType) { if (value == null && Nullable.GetUnderlyingType(TypeToConvert) == (Type)null) ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && value != null) state.ReferenceResolver.PushReferenceForCycleDetection(value); } T value2 = (T)value; return WriteCore(writer, ref value2, options, ref state); } internal bool WriteCore(Utf8JsonWriter writer, [In] [System.Runtime.CompilerServices.IsReadOnly] ref T value, JsonSerializerOptions options, ref WriteStack state) { try { return TryWrite(writer, ref value, options, ref state); } catch (InvalidOperationException ex) when (ex.Source == "System.Text.Json.Rethrowable") { ThrowHelper.ReThrowWithPath(ref state, ex); throw; } catch (JsonException ex2) when (ex2.Path == null) { ThrowHelper.AddJsonExceptionInformation(ref state, ex2); throw; } catch (NotSupportedException ex3) { if (ex3.Message.Contains(" Path: ")) throw; ThrowHelper.ThrowNotSupportedException(ref state, ex3); return false; } } protected internal JsonConverter() { base.IsInternalConverter = (GetType().Assembly == typeof(JsonConverter).Assembly); base.CanBePolymorphic = (base.IsInternalConverter && TypeToConvert == JsonTypeInfo.ObjectType); base.IsValueType = TypeToConvert.IsValueType; CanBeNull = (default(T) == null); if (HandleNull) { HandleNullOnRead = true; HandleNullOnWrite = true; } base.CanUseDirectReadOrWrite = (!base.CanBePolymorphic && base.IsInternalConverter && ConverterStrategy == ConverterStrategy.Value); } public override bool CanConvert(Type typeToConvert) { return typeToConvert == typeof(T); } internal sealed override JsonPropertyInfo CreateJsonPropertyInfo() { return new JsonPropertyInfo<T>(); } internal sealed override JsonParameterInfo CreateJsonParameterInfo() { return new JsonParameterInfo<T>(); } internal sealed override bool TryWriteAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, ref WriteStack state) { T value2 = (T)value; return TryWrite(writer, ref value2, options, ref state); } internal virtual bool OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state) { Write(writer, value, options); return true; } internal virtual bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T value) { value = Read(ref reader, typeToConvert, options); return true; } [return: System.Runtime.CompilerServices.Nullable(2)] public abstract T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options); internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T value) { if (ConverterStrategy == ConverterStrategy.Value) { if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead) { if (!CanBeNull) ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); value = default(T); return true; } if (base.IsInternalConverter) { if (state.Current.NumberHandling.HasValue && IsInternalConverterForNumberType) value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options); else value = Read(ref reader, typeToConvert, options); } else { JsonTokenType tokenType = reader.TokenType; int currentDepth = reader.CurrentDepth; long bytesConsumed = reader.BytesConsumed; if (state.Current.NumberHandling.HasValue && IsInternalConverterForNumberType) value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options); else value = Read(ref reader, typeToConvert, options); VerifyRead(tokenType, currentDepth, bytesConsumed, true, ref reader); } if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve && base.CanBePolymorphic) { T val = value; if (((object)val) is JsonElement) { JsonElement element = val as JsonElement; if (JsonSerializer.TryGetReferenceFromJsonElement(ref state, element, out object referenceValue)) value = (T)referenceValue; } } return true; } bool isContinuation = state.IsContinuation; state.Push(); bool flag; if (base.IsInternalConverter) { if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead && !isContinuation) { if (!CanBeNull) ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); value = default(T); flag = true; } else flag = OnTryRead(ref reader, typeToConvert, options, ref state, out value); } else { if (!isContinuation) { if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead) { if (!CanBeNull) ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); value = default(T); state.Pop(true); return true; } state.Current.OriginalTokenType = reader.TokenType; state.Current.OriginalDepth = reader.CurrentDepth; } flag = OnTryRead(ref reader, typeToConvert, options, ref state, out value); if (flag) { if (state.IsContinuation) ThrowHelper.ThrowJsonException_SerializationConverterRead(this); VerifyRead(state.Current.OriginalTokenType, state.Current.OriginalDepth, 0, false, ref reader); } } state.Pop(flag); return flag; } internal sealed override bool TryReadAsObject(ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state, out object value) { T value2; bool result = TryRead(ref reader, TypeToConvert, options, ref state, out value2); value = value2; return result; } private static bool IsNull(T value) { return value == null; } internal bool TryWrite(Utf8JsonWriter writer, [In] [System.Runtime.CompilerServices.IsReadOnly] ref T value, JsonSerializerOptions options, ref WriteStack state) { if (writer.CurrentDepth >= options.EffectiveMaxDepth) ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth); T val = default(T); if (val == null && !HandleNullOnWrite && IsNull(value)) { writer.WriteNullValue(); return true; } bool flag = false; if (!base.IsValueType && value != null) { if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.IgnoreCycles && ConverterStrategy != ConverterStrategy.Value) { ReferenceResolver referenceResolver = state.ReferenceResolver; if (referenceResolver.ContainsReferenceForCycleDetection(value)) { writer.WriteNullValue(); return true; } referenceResolver.PushReferenceForCycleDetection(value); flag = true; } if (base.CanBePolymorphic) { val = value; Type type = val.GetType(); if (type != TypeToConvert) { JsonConverter jsonConverter = state.Current.InitializeReEntry(type, options); if (jsonConverter.IsValueType) { switch (options.ReferenceHandlingStrategy) { case ReferenceHandlingStrategy.Preserve: if (jsonConverter.CanHaveIdMetadata && !state.IsContinuation && JsonSerializer.TryWriteReferenceForBoxedStruct(value, ref state, writer)) return true; break; case ReferenceHandlingStrategy.IgnoreCycles: state.ReferenceResolver.PushReferenceForCycleDetection(value); flag = true; break; } } bool result = jsonConverter.TryWriteAsObject(writer, value, options, ref state); if (flag) state.ReferenceResolver.PopReferenceForCycleDetection(); return result; } } } if (ConverterStrategy == ConverterStrategy.Value) { int currentDepth = writer.CurrentDepth; if (state.Current.NumberHandling.HasValue && IsInternalConverterForNumberType) WriteNumberWithCustomHandling(writer, value, state.Current.NumberHandling.Value); else Write(writer, value, options); VerifyWrite(currentDepth, writer); if (flag) state.ReferenceResolver.PopReferenceForCycleDetection(); return true; } bool isContinuation = state.IsContinuation; state.Push(); if (!isContinuation) state.Current.OriginalDepth = writer.CurrentDepth; bool flag2 = OnTryWrite(writer, value, options, ref state); if (flag2) VerifyWrite(state.Current.OriginalDepth, writer); state.Pop(flag2); if (flag) state.ReferenceResolver.PopReferenceForCycleDetection(); return flag2; } internal bool TryWriteDataExtensionProperty(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state) { if (!base.IsInternalConverter) return TryWrite(writer, ref value, options, ref state); object obj = this as JsonDictionaryConverter<T>; if (obj == null) { JsonMetadataServicesConverter<T> obj2 = this as JsonMetadataServicesConverter<T>; obj = (((obj2 != null) ? obj2.Converter : null) as JsonDictionaryConverter<T>); } JsonDictionaryConverter<T> jsonDictionaryConverter = (JsonDictionaryConverter<T>)obj; if (jsonDictionaryConverter == null) return TryWrite(writer, ref value, options, ref state); if (writer.CurrentDepth >= options.EffectiveMaxDepth) ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth); bool isContinuation = state.IsContinuation; state.Push(); if (!isContinuation) state.Current.OriginalDepth = writer.CurrentDepth; state.Current.IsWritingExtensionDataProperty = true; state.Current.DeclaredJsonPropertyInfo = state.Current.JsonTypeInfo.ElementTypeInfo.PropertyInfoForTypeInfo; bool flag = jsonDictionaryConverter.OnWriteResume(writer, value, options, ref state); if (flag) VerifyWrite(state.Current.OriginalDepth, writer); state.Pop(flag); return flag; } internal void VerifyRead(JsonTokenType tokenType, int depth, long bytesConsumed, bool isValueConverter, ref Utf8JsonReader reader) { switch (tokenType) { case JsonTokenType.StartArray: if (reader.TokenType != JsonTokenType.EndArray) ThrowHelper.ThrowJsonException_SerializationConverterRead(this); else if (depth != reader.CurrentDepth) { ThrowHelper.ThrowJsonException_SerializationConverterRead(this); } break; case JsonTokenType.StartObject: if (reader.TokenType != JsonTokenType.EndObject) ThrowHelper.ThrowJsonException_SerializationConverterRead(this); else if (depth != reader.CurrentDepth) { ThrowHelper.ThrowJsonException_SerializationConverterRead(this); } break; default: if (!isValueConverter) { if (!HandleNullOnRead || tokenType != JsonTokenType.Null) ThrowHelper.ThrowJsonException_SerializationConverterRead(this); } else if (reader.BytesConsumed != bytesConsumed) { ThrowHelper.ThrowJsonException_SerializationConverterRead(this); } break; } } internal void VerifyWrite(int originalDepth, Utf8JsonWriter writer) { if (originalDepth != writer.CurrentDepth) ThrowHelper.ThrowJsonException_SerializationConverterWrite(this); } public abstract void Write(Utf8JsonWriter writer, [System.Runtime.CompilerServices.Nullable(0)] T value, JsonSerializerOptions options); public virtual T ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (!base.IsInternalConverter && options.TryGetDefaultSimpleConverter(TypeToConvert, out JsonConverter converter)) return ((JsonConverter<T>)converter).ReadAsPropertyNameCore(ref reader, TypeToConvert, options); ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); return default(T); } internal virtual T ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { long bytesConsumed = reader.BytesConsumed; T result = ReadAsPropertyName(ref reader, typeToConvert, options); if (reader.BytesConsumed != bytesConsumed) ThrowHelper.ThrowJsonException_SerializationConverterRead(this); return result; } public virtual void WriteAsPropertyName(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { if (!base.IsInternalConverter && options.TryGetDefaultSimpleConverter(TypeToConvert, out JsonConverter converter)) ((JsonConverter<T>)converter).WriteAsPropertyNameCore(writer, value, options, false); else ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); } internal virtual void WriteAsPropertyNameCore(Utf8JsonWriter writer, T value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { if (isWritingExtensionDataProperty) writer.WritePropertyName((string)(object)value); else { int currentDepth = writer.CurrentDepth; WriteAsPropertyName(writer, value, options); if (currentDepth != writer.CurrentDepth || writer.TokenType != JsonTokenType.PropertyName) ThrowHelper.ThrowJsonException_SerializationConverterWrite(this); } } internal sealed override void WriteAsPropertyNameCoreAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { WriteAsPropertyNameCore(writer, (T)value, options, isWritingExtensionDataProperty); } internal virtual T ReadNumberWithCustomHandling(ref Utf8JsonReader reader, JsonNumberHandling handling, JsonSerializerOptions options) { throw new InvalidOperationException(); } internal virtual void WriteNumberWithCustomHandling(Utf8JsonWriter writer, T value, JsonNumberHandling handling) { throw new InvalidOperationException(); } } }