ObjectDefaultConverter<T>
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Text.Json.Serialization.Metadata;
namespace System.Text.Json.Serialization.Converters
{
internal class ObjectDefaultConverter<T> : JsonObjectConverter<T>
{
internal override bool CanHaveMetadata => true;
internal override bool SupportsCreateObjectDelegate => true;
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, [MaybeNullWhen(false)] out T value)
{
JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo;
object obj;
if (!state.SupportContinuation && !state.Current.CanContainMetadata) {
if (reader.TokenType != JsonTokenType.StartObject)
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
if (jsonTypeInfo.CreateObject == null)
ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(jsonTypeInfo.Type, ref reader, ref state);
obj = jsonTypeInfo.CreateObject();
jsonTypeInfo.OnDeserializing?.Invoke(obj);
state.Current.InitializeRequiredPropertiesValidationState(jsonTypeInfo);
while (true) {
ref reader.ReadWithVerify();
JsonTokenType tokenType = reader.TokenType;
if (tokenType == JsonTokenType.EndObject)
break;
ReadOnlySpan<byte> propertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options);
bool useExtensionProperty;
JsonPropertyInfo jsonPropertyInfo = JsonSerializer.LookupProperty(obj, propertyName, ref state, options, out useExtensionProperty, true);
ReadPropertyValue(obj, ref state, ref reader, jsonPropertyInfo, useExtensionProperty);
}
} else {
if (state.Current.ObjectState == StackFrameObjectState.None) {
if (reader.TokenType != JsonTokenType.StartObject)
ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
state.Current.ObjectState = StackFrameObjectState.StartToken;
}
if (state.Current.CanContainMetadata && (int)state.Current.ObjectState < 2) {
if (!JsonSerializer.TryReadMetadata(this, jsonTypeInfo, ref reader, ref state)) {
value = default(T);
return false;
}
if (state.Current.MetadataPropertyNames == MetadataPropertyName.Ref) {
value = JsonSerializer.ResolveReferenceId<T>(ref state);
return true;
}
state.Current.ObjectState = StackFrameObjectState.ReadMetadata;
}
if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted) {
JsonConverter jsonConverter = ResolvePolymorphicConverter(jsonTypeInfo, options, ref state);
if (jsonConverter != null) {
object value2;
bool flag = jsonConverter.OnTryReadAsObject(ref reader, options, ref state, out value2);
value = (T)value2;
state.ExitPolymorphicConverter(flag);
return flag;
}
}
if ((int)state.Current.ObjectState < 4) {
if (state.Current.CanContainMetadata)
JsonSerializer.ValidateMetadataForObjectConverter(this, ref reader, ref state);
if (state.Current.MetadataPropertyNames == MetadataPropertyName.Ref) {
value = JsonSerializer.ResolveReferenceId<T>(ref state);
return true;
}
if (jsonTypeInfo.CreateObject == null)
ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(jsonTypeInfo.Type, ref reader, ref state);
obj = jsonTypeInfo.CreateObject();
if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) {
state.ReferenceResolver.AddReference(state.ReferenceId, obj);
state.ReferenceId = null;
}
jsonTypeInfo.OnDeserializing?.Invoke(obj);
state.Current.ReturnValue = obj;
state.Current.ObjectState = StackFrameObjectState.CreatedObject;
state.Current.InitializeRequiredPropertiesValidationState(jsonTypeInfo);
} else
obj = state.Current.ReturnValue;
while (true) {
if (state.Current.PropertyState == StackFramePropertyState.None) {
state.Current.PropertyState = StackFramePropertyState.ReadName;
if (!reader.Read()) {
state.Current.ReturnValue = obj;
value = default(T);
return false;
}
}
JsonPropertyInfo jsonPropertyInfo2;
if ((int)state.Current.PropertyState < 2) {
state.Current.PropertyState = StackFramePropertyState.Name;
JsonTokenType tokenType2 = reader.TokenType;
if (tokenType2 == JsonTokenType.EndObject)
break;
ReadOnlySpan<byte> propertyName2 = JsonSerializer.GetPropertyName(ref state, ref reader, options);
jsonPropertyInfo2 = JsonSerializer.LookupProperty(obj, propertyName2, ref state, options, out bool useExtensionProperty2, true);
state.Current.UseExtensionProperty = useExtensionProperty2;
} else
jsonPropertyInfo2 = state.Current.JsonPropertyInfo;
if ((int)state.Current.PropertyState < 3) {
if (!jsonPropertyInfo2.CanDeserialize) {
if (!reader.TrySkip()) {
state.Current.ReturnValue = obj;
value = default(T);
return false;
}
state.Current.EndProperty();
continue;
}
if (!ReadAheadPropertyValue(ref state, ref reader, jsonPropertyInfo2)) {
state.Current.ReturnValue = obj;
value = default(T);
return false;
}
}
if ((int)state.Current.PropertyState < 5) {
if (!state.Current.UseExtensionProperty) {
if (!jsonPropertyInfo2.ReadJsonAndSetMember(obj, ref state, ref reader)) {
state.Current.ReturnValue = obj;
value = default(T);
return false;
}
} else if (!jsonPropertyInfo2.ReadJsonAndAddExtensionProperty(obj, ref state, ref reader)) {
state.Current.ReturnValue = obj;
value = default(T);
return false;
}
state.Current.EndProperty();
}
}
}
jsonTypeInfo.OnDeserialized?.Invoke(obj);
state.Current.ValidateAllRequiredPropertiesAreRead(jsonTypeInfo);
value = (T)obj;
if (state.Current.PropertyRefCache != null)
jsonTypeInfo.UpdateSortedPropertyCache(ref state.Current);
return true;
}
internal sealed override bool OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state)
{
JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo;
object obj = value;
KeyValuePair<string, JsonPropertyInfo> keyValuePair;
if (!state.SupportContinuation) {
writer.WriteStartObject();
if (state.CurrentContainsMetadata && CanHaveMetadata)
JsonSerializer.WriteMetadataForObject(this, ref state, writer);
jsonTypeInfo.OnSerializing?.Invoke(obj);
List<KeyValuePair<string, JsonPropertyInfo>> list = jsonTypeInfo.PropertyCache.List;
for (int i = 0; i < list.Count; i++) {
keyValuePair = list[i];
JsonPropertyInfo value2 = keyValuePair.Value;
if (value2.CanSerialize) {
state.Current.JsonPropertyInfo = value2;
state.Current.NumberHandling = value2.EffectiveNumberHandling;
bool memberAndWriteJson = value2.GetMemberAndWriteJson(obj, ref state, writer);
state.Current.EndProperty();
}
}
JsonPropertyInfo extensionDataProperty = jsonTypeInfo.ExtensionDataProperty;
if (extensionDataProperty != null && extensionDataProperty.CanSerialize) {
state.Current.JsonPropertyInfo = extensionDataProperty;
state.Current.NumberHandling = extensionDataProperty.EffectiveNumberHandling;
bool memberAndWriteJsonExtensionData = extensionDataProperty.GetMemberAndWriteJsonExtensionData(obj, ref state, writer);
state.Current.EndProperty();
}
writer.WriteEndObject();
} else {
if (!state.Current.ProcessedStartToken) {
writer.WriteStartObject();
if (state.CurrentContainsMetadata && CanHaveMetadata)
JsonSerializer.WriteMetadataForObject(this, ref state, writer);
jsonTypeInfo.OnSerializing?.Invoke(obj);
state.Current.ProcessedStartToken = true;
}
List<KeyValuePair<string, JsonPropertyInfo>> list2 = jsonTypeInfo.PropertyCache.List;
while (state.Current.EnumeratorIndex < list2.Count) {
keyValuePair = list2[state.Current.EnumeratorIndex];
JsonPropertyInfo value3 = keyValuePair.Value;
if (value3.CanSerialize) {
state.Current.JsonPropertyInfo = value3;
state.Current.NumberHandling = value3.EffectiveNumberHandling;
if (!value3.GetMemberAndWriteJson(obj, ref state, writer))
return false;
state.Current.EndProperty();
state.Current.EnumeratorIndex++;
if (JsonConverter.ShouldFlush(writer, ref state))
return false;
} else
state.Current.EnumeratorIndex++;
}
if (state.Current.EnumeratorIndex == list2.Count) {
JsonPropertyInfo extensionDataProperty2 = jsonTypeInfo.ExtensionDataProperty;
if (extensionDataProperty2 != null && extensionDataProperty2.CanSerialize) {
state.Current.JsonPropertyInfo = extensionDataProperty2;
state.Current.NumberHandling = extensionDataProperty2.EffectiveNumberHandling;
if (!extensionDataProperty2.GetMemberAndWriteJsonExtensionData(obj, ref state, writer))
return false;
state.Current.EndProperty();
state.Current.EnumeratorIndex++;
if (JsonConverter.ShouldFlush(writer, ref state))
return false;
} else
state.Current.EnumeratorIndex++;
}
if (!state.Current.ProcessedEndToken) {
state.Current.ProcessedEndToken = true;
writer.WriteEndObject();
}
}
jsonTypeInfo.OnSerialized?.Invoke(obj);
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected static void ReadPropertyValue(object obj, [System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, JsonPropertyInfo jsonPropertyInfo, bool useExtensionProperty)
{
if (!jsonPropertyInfo.CanDeserialize)
reader.Skip();
else {
ref reader.ReadWithVerify();
if (!useExtensionProperty)
jsonPropertyInfo.ReadJsonAndSetMember(obj, ref state, ref reader);
else
jsonPropertyInfo.ReadJsonAndAddExtensionProperty(obj, ref state, ref reader);
}
state.Current.EndProperty();
}
protected static bool ReadAheadPropertyValue([System.Runtime.CompilerServices.ScopedRef] ref ReadStack state, ref Utf8JsonReader reader, JsonPropertyInfo jsonPropertyInfo)
{
state.Current.PropertyState = StackFramePropertyState.ReadValue;
if (!state.Current.UseExtensionProperty) {
if (!JsonConverter.SingleValueReadWithReadAhead(jsonPropertyInfo.EffectiveConverter.RequiresReadAhead, ref reader, ref state))
return false;
} else if (!JsonConverter.SingleValueReadWithReadAhead(true, ref reader, ref state)) {
return false;
}
return true;
}
}
}