JsonConverter<T>
Converts an object or value to or from JSON.
using System.Diagnostics.CodeAnalysis;
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
{
private JsonConverter<T> _fallbackConverterForPropertyNameSerialization;
[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 {
base.UsesDefaultHandleNull = true;
return false;
}
}
public sealed override Type Type { get; } = typeof(T);
internal T ReadCore(ref Utf8JsonReader reader, JsonSerializerOptions options, ref ReadStack state)
{
try {
if (!state.IsContinuation) {
if (!JsonConverter.SingleValueReadWithReadAhead(base.RequiresReadAhead, 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(true, ref reader, ref state)) {
state.BytesConsumed += reader.BytesConsumed;
return default(T);
}
if (TryRead(ref reader, state.Current.JsonTypeInfo.Type, options, ref state, out T value, out bool _) && !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 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.IsValueType = typeof(T).IsValueType;
if (HandleNull) {
base.HandleNullOnRead = true;
base.HandleNullOnWrite = true;
} else if (base.UsesDefaultHandleNull) {
base.HandleNullOnRead = (default(T) != null);
base.HandleNullOnWrite = false;
}
}
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert == typeof(T);
}
private protected override ConverterStrategy GetDefaultConverterStrategy()
{
return ConverterStrategy.Value;
}
internal sealed override JsonTypeInfo CreateJsonTypeInfo(JsonSerializerOptions options)
{
return new JsonTypeInfo<T>(this, options);
}
internal sealed override void WriteAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
T value2 = JsonSerializer.UnboxOnWrite<T>(value);
Write(writer, value2, options);
}
internal sealed override bool OnTryWriteAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, ref WriteStack state)
{
T value2 = JsonSerializer.UnboxOnWrite<T>(value);
return OnTryWrite(writer, value2, options, ref state);
}
internal sealed override void WriteAsPropertyNameAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
{
T value2 = JsonSerializer.UnboxOnWrite<T>(value);
WriteAsPropertyName(writer, value2, options);
}
internal sealed override void WriteAsPropertyNameCoreAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, bool isWritingExtensionDataProperty)
{
T value2 = JsonSerializer.UnboxOnWrite<T>(value);
WriteAsPropertyNameCore(writer, value2, options, isWritingExtensionDataProperty);
}
internal sealed override void WriteNumberWithCustomHandlingAsObject(Utf8JsonWriter writer, object value, JsonNumberHandling handling)
{
T value2 = JsonSerializer.UnboxOnWrite<T>(value);
WriteNumberWithCustomHandling(writer, value2, handling);
}
internal sealed override bool TryWriteAsObject(Utf8JsonWriter writer, object value, JsonSerializerOptions options, ref WriteStack state)
{
T value2 = JsonSerializer.UnboxOnWrite<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, [System.Runtime.CompilerServices.ScopedRef] 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, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, out T value, out bool isPopulatedValue)
{
if (reader.TokenType == JsonTokenType.Null && !base.HandleNullOnRead && !state.IsContinuation) {
if (default(T) != null)
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type);
value = default(T);
isPopulatedValue = false;
return true;
}
if (base.ConverterStrategy == ConverterStrategy.Value) {
if (base.IsInternalConverter) {
if (state.Current.NumberHandling.HasValue && base.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 && base.IsInternalConverterForNumberType)
value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
else
value = Read(ref reader, typeToConvert, options);
VerifyRead(tokenType, currentDepth, bytesConsumed, true, ref reader);
}
isPopulatedValue = false;
return true;
}
bool isContinuation = state.IsContinuation;
bool flag;
if (base.CanBePolymorphic) {
flag = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
isPopulatedValue = false;
return true;
}
JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;
object returnValue = state.Current.ReturnValue;
state.Push();
if (returnValue != null && jsonPropertyInfo != null && !jsonPropertyInfo.IsForTypeInfo)
state.Current.HasParentObject = true;
flag = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
isPopulatedValue = state.Current.IsPopulating;
state.Pop(flag);
return flag;
}
internal sealed override bool OnTryReadAsObject(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, out object value)
{
T value2;
bool result = OnTryRead(ref reader, typeToConvert, options, ref state, out value2);
value = value2;
return result;
}
internal sealed override bool TryReadAsObject(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, out object value)
{
T value2;
bool isPopulatedValue;
bool result = TryRead(ref reader, typeToConvert, options, ref state, out value2, out isPopulatedValue);
value = value2;
return result;
}
internal sealed override object ReadAsObject(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
T val = Read(ref reader, typeToConvert, options);
return val;
}
internal sealed override object ReadAsPropertyNameAsObject(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
T val = ReadAsPropertyName(ref reader, typeToConvert, options);
return val;
}
internal sealed override object ReadAsPropertyNameCoreAsObject(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
T val = ReadAsPropertyNameCore(ref reader, typeToConvert, options);
return val;
}
internal sealed override object ReadNumberWithCustomHandlingAsObject(ref Utf8JsonReader reader, JsonNumberHandling handling, JsonSerializerOptions options)
{
T val = ReadNumberWithCustomHandling(ref reader, handling, options);
return val;
}
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);
if (default(T) == null && !base.HandleNullOnWrite && IsNull(value)) {
writer.WriteNullValue();
return true;
}
if (base.ConverterStrategy == ConverterStrategy.Value) {
int currentDepth = writer.CurrentDepth;
if (state.Current.NumberHandling.HasValue && base.IsInternalConverterForNumberType)
WriteNumberWithCustomHandling(writer, value, state.Current.NumberHandling.Value);
else
Write(writer, value, options);
VerifyWrite(currentDepth, writer);
return true;
}
bool isContinuation = state.IsContinuation;
bool flag;
if (!base.IsValueType && value != null && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted) {
JsonTypeInfo jsonTypeInfo = state.PeekNestedJsonTypeInfo();
JsonConverter jsonConverter = (base.CanBePolymorphic || jsonTypeInfo.PolymorphicTypeResolver != null) ? ResolvePolymorphicConverter(value, jsonTypeInfo, options, ref state) : null;
if (!isContinuation && options.ReferenceHandlingStrategy != 0 && TryHandleSerializedObjectReference(writer, value, options, jsonConverter, ref state))
return true;
if (jsonConverter != null) {
flag = jsonConverter.TryWriteAsObject(writer, value, options, ref state);
state.Current.ExitPolymorphicConverter(flag);
if (flag && state.Current.IsPushedReferenceForCycleDetection) {
state.ReferenceResolver.PopReferenceForCycleDetection();
state.Current.IsPushedReferenceForCycleDetection = false;
}
return flag;
}
}
state.Push();
flag = OnTryWrite(writer, value, options, ref state);
state.Pop(flag);
if (flag && state.Current.IsPushedReferenceForCycleDetection) {
state.ReferenceResolver.PopReferenceForCycleDetection();
state.Current.IsPushedReferenceForCycleDetection = false;
}
return flag;
}
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.JsonPropertyInfo = 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 (reader.BytesConsumed != bytesConsumed)
ThrowHelper.ThrowJsonException_SerializationConverterRead(this);
} else if (!base.CanBePolymorphic && (!base.HandleNullOnRead || tokenType != JsonTokenType.Null)) {
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)
{
JsonConverter<T> fallbackConverterForPropertyNameSerialization = GetFallbackConverterForPropertyNameSerialization(options);
if (fallbackConverterForPropertyNameSerialization == null)
ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(Type, this);
return fallbackConverterForPropertyNameSerialization.ReadAsPropertyNameCore(ref reader, typeToConvert, options);
}
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, [System.Diagnostics.CodeAnalysis.DisallowNull] T value, JsonSerializerOptions options)
{
JsonConverter<T> fallbackConverterForPropertyNameSerialization = GetFallbackConverterForPropertyNameSerialization(options);
if (fallbackConverterForPropertyNameSerialization == null)
ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(Type, this);
fallbackConverterForPropertyNameSerialization.WriteAsPropertyNameCore(writer, value, options, false);
}
internal virtual void WriteAsPropertyNameCore(Utf8JsonWriter writer, [System.Diagnostics.CodeAnalysis.DisallowNull] T value, JsonSerializerOptions options, bool isWritingExtensionDataProperty)
{
if (value == null)
ThrowHelper.ThrowArgumentNullException("value");
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);
}
}
private JsonConverter<T> GetFallbackConverterForPropertyNameSerialization(JsonSerializerOptions options)
{
JsonConverter<T> jsonConverter = null;
if (!base.IsInternalConverter && !(options.TypeInfoResolver is JsonSerializerContext)) {
jsonConverter = _fallbackConverterForPropertyNameSerialization;
if (jsonConverter == null && DefaultJsonTypeInfoResolver.TryGetDefaultSimpleConverter(Type, out JsonConverter converter))
jsonConverter = (_fallbackConverterForPropertyNameSerialization = (JsonConverter<T>)converter);
}
return jsonConverter;
}
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();
}
}
}