internal sealed override bool OnTryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { object obj = default; // Slower path that supports continuation. if (state.Current.ObjectState == StackFrameObjectState.None) { if (!reader.ReadStartToken()) { value = default; return(false); } RefState refState = BinarySerializer.ReadReferenceForObject(this, ref state, ref reader, out object refValue); if (refState == RefState.None) { state.Current.ObjectState = StackFrameObjectState.StartToken; BeginRead(ref state, ref reader, options); } else if (refState == RefState.Created) { state.Current.ObjectState = StackFrameObjectState.CreatedObject; obj = (T)refValue; } else { value = default; return(false); } } // 读取构造参数 if (!ReadCreatorArgumentsWithContinuation(ref state, ref reader, options)) { value = default; return(false); } if (state.Current.ObjectState < StackFrameObjectState.CreatedObject) { obj = CreateObject(ref state.Current); state.ReferenceResolver.AddReferenceObject(state.Current.RefId, obj); } EndRead(ref state); value = (T)obj; return(true); }
protected virtual void ConvertCollection(ref ReadStack state, JsonSerializerOptions options) { }
protected override void Add(TElement value, ref ReadStack state) { Debug.Assert(state.Current.ReturnValue is TCollection); ((TCollection)state.Current.ReturnValue !).Push(value); }
internal sealed override bool OnTryRead( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out TCollection value) { bool shouldReadPreservedReferences = options.ReferenceHandling.ShouldReadPreservedReferences(); if (!state.SupportContinuation && !shouldReadPreservedReferences) { // Fast path that avoids maintaining state variables and dealing with preserved references. if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } CreateCollection(ref state); JsonConverter <TValue> elementConverter = GetElementConverter(ref state); if (elementConverter.CanUseDirectReadOrWrite) { // Process all elements. while (true) { // Read the key name. reader.ReadWithVerify(); if (reader.TokenType == JsonTokenType.EndObject) { break; } if (reader.TokenType != JsonTokenType.PropertyName) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.JsonPropertyNameAsString = reader.GetString(); // Read the value and add. reader.ReadWithVerify(); TValue element = elementConverter.Read(ref reader, typeof(TValue), options); Add(element, options, ref state); } } else { // Process all elements. while (true) { // Read the key name. reader.ReadWithVerify(); if (reader.TokenType == JsonTokenType.EndObject) { break; } if (reader.TokenType != JsonTokenType.PropertyName) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.JsonPropertyNameAsString = reader.GetString(); reader.ReadWithVerify(); // Get the value from the converter and add it. elementConverter.TryRead(ref reader, typeof(TValue), options, ref state, out TValue element); Add(element, options, ref state); } } } else { // Slower path that supports continuation and preserved references. if (state.Current.ObjectState == StackFrameObjectState.None) { if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.StartToken; } // Handle the metadata properties. if (shouldReadPreservedReferences && state.Current.ObjectState < StackFrameObjectState.MetadataPropertyValue) { if (JsonSerializer.ResolveMetadata(this, ref reader, ref state)) { if (state.Current.ObjectState == StackFrameObjectState.MetadataRefPropertyEndObject) { value = (TCollection)state.Current.ReturnValue !; return(true); } } else { value = default !;
protected abstract void Add(TElement value, ref ReadStack state);
internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { object obj; ArgumentState argumentState = state.Current.CtorArgumentState !; if (state.UseFastPath) { // Fast path that avoids maintaining state variables. ReadOnlySpan <byte> originalSpan = reader.OriginalSpan; ReadConstructorArguments(ref state, ref reader, options); obj = CreateObject(ref state.Current); if (argumentState.FoundPropertyCount > 0) { Utf8JsonReader tempReader; FoundProperty[]? properties = argumentState.FoundProperties; Debug.Assert(properties != null); for (int i = 0; i < argumentState.FoundPropertyCount; i++) { JsonPropertyInfo jsonPropertyInfo = properties[i].Item1; long resumptionByteIndex = properties[i].Item3; byte[]? propertyNameArray = properties[i].Item4; string?dataExtKey = properties[i].Item5; tempReader = new Utf8JsonReader( originalSpan.Slice(checked ((int)resumptionByteIndex)), isFinalBlock: true, state: properties[i].Item2); Debug.Assert(tempReader.TokenType == JsonTokenType.PropertyName); state.Current.JsonPropertyName = propertyNameArray; state.Current.JsonPropertyInfo = jsonPropertyInfo; state.Current.NumberHandling = jsonPropertyInfo.NumberHandling; bool useExtensionProperty = dataExtKey != null; if (useExtensionProperty) { Debug.Assert(jsonPropertyInfo == state.Current.JsonClassInfo.DataExtensionProperty); state.Current.JsonPropertyNameAsString = dataExtKey; JsonSerializer.CreateDataExtensionProperty(obj, jsonPropertyInfo); } ReadPropertyValue(obj, ref state, ref tempReader, jsonPropertyInfo, useExtensionProperty); } ArrayPool <FoundProperty> .Shared.Return(argumentState.FoundProperties !, clearArray: true); argumentState.FoundProperties = null; } } else { // Slower path that supports continuation. if (state.Current.ObjectState == StackFrameObjectState.None) { state.Current.ObjectState = StackFrameObjectState.StartToken; BeginRead(ref state, ref reader, options); } if (!ReadConstructorArgumentsWithContinuation(ref state, ref reader, options)) { value = default; return(false); } obj = CreateObject(ref state.Current); if (argumentState.FoundPropertyCount > 0) { for (int i = 0; i < argumentState.FoundPropertyCount; i++) { JsonPropertyInfo jsonPropertyInfo = argumentState.FoundPropertiesAsync ![i].Item1;
/// <summary> /// When overridden, adds the value to the collection. /// </summary> protected abstract void Add(TValue value, JsonSerializerOptions options, ref ReadStack state);
protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options) { state.Current.ReturnValue = new List <TElement>(); }
protected override void ConvertCollection(ref ReadStack state, JsonSerializerOptions options) { List <TElement> list = (List <TElement>)state.Current.ReturnValue !; state.Current.ReturnValue = list.ToArray(); }
internal override bool OnTryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, out T?value) { if (reader.TokenType == BinaryTokenType.Null) { value = null; return(true); } if (state.Current.ObjectState < StackFrameObjectState.CreatedObject) { if (!reader.ReadTypeSeq()) { value = default; return(false); } state.Current.ObjectState = StackFrameObjectState.CreatedObject; } if (!_converter.TryRead(ref reader, typeof(T), options, ref state, out ReferenceID refId, out T typedValue)) { value = default; return(false); } value = typedValue; return(true); //if (!reader.ReadTypeSeq()) //{ // return null; //} //T value = _converter.Read(ref reader, typeof(T), options); //return value; }
protected override void Add(TElement value, ref ReadStack state) { ((List <TElement>)state.Current.ReturnValue !).Add(value); }
private static bool HandleValue(JsonTokenType tokenType, JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state) { if (state.Current.SkipProperty) { return(false); } JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (jsonPropertyInfo == null) { jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootObject(options); } else if (state.Current.JsonClassInfo.ClassType == ClassType.Unknown) { jsonPropertyInfo = state.Current.JsonClassInfo.CreatePolymorphicProperty(jsonPropertyInfo, typeof(object), options); } bool lastCall = (!state.Current.IsProcessingEnumerableOrDictionary && state.Current.ReturnValue == null); jsonPropertyInfo.Read(tokenType, options, ref state, ref reader); return(lastCall); }
protected abstract void InitializeCreatorArgumentCaches(ref ReadStack state, BinarySerializerOptions options);
protected virtual void EndRead(ref ReadStack state) { }
internal abstract bool TryReadAsObject(ref BinaryReader reader, BinarySerializerOptions options, ref ReadStack state, out object value);
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T?value) { JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo; if (_converterStrategy == ConverterStrategy.Object && jsonTypeInfo.PropertyCache == null) { jsonTypeInfo.InitializePropCache(); } return(Converter.OnTryRead(ref reader, typeToConvert, options, ref state, out value)); }
/// <summary> /// Creates the instance and assigns it to state.Current.ReturnValue. /// </summary> internal virtual void CreateInstanceForReferenceResolver(ref BinaryReader reader, ref ReadStack state, BinarySerializerOptions options) { }
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out object?value) { object?referenceValue; if (options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonElement) { JsonElement element = JsonElement.ParseValue(ref reader); // Edge case where we want to lookup for a reference when parsing into typeof(object) if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve && JsonSerializer.TryHandleReferenceFromJsonElement(ref reader, ref state, element, out referenceValue)) { value = referenceValue; } else { value = element; } return(true); } Debug.Assert(options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonNode); JsonNode node = JsonNodeConverter.Instance.Read(ref reader, typeToConvert, options) !; if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve && JsonSerializer.TryHandleReferenceFromJsonNode(ref reader, ref state, node, out referenceValue)) { value = referenceValue; } else { value = node; } return(true); }
internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo; if (jsonTypeInfo.CreateObject != null) { // Contract customization: fall back to default object converter if user has set a default constructor delegate. return(base.OnTryRead(ref reader, typeToConvert, options, ref state, out value)); } object obj; ArgumentState argumentState = state.Current.CtorArgumentState !; if (!state.SupportContinuation && !state.Current.CanContainMetadata) { // Fast path that avoids maintaining state variables. if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } ReadOnlySpan <byte> originalSpan = reader.OriginalSpan; ReadConstructorArguments(ref state, ref reader, options); obj = (T)CreateObject(ref state.Current); jsonTypeInfo.OnDeserializing?.Invoke(obj); if (argumentState.FoundPropertyCount > 0) { Utf8JsonReader tempReader; FoundProperty[]? properties = argumentState.FoundProperties; Debug.Assert(properties != null); for (int i = 0; i < argumentState.FoundPropertyCount; i++) { JsonPropertyInfo jsonPropertyInfo = properties[i].Item1; long resumptionByteIndex = properties[i].Item3; byte[]? propertyNameArray = properties[i].Item4; string?dataExtKey = properties[i].Item5; tempReader = new Utf8JsonReader( originalSpan.Slice(checked ((int)resumptionByteIndex)), isFinalBlock: true, state: properties[i].Item2); Debug.Assert(tempReader.TokenType == JsonTokenType.PropertyName); state.Current.JsonPropertyName = propertyNameArray; state.Current.JsonPropertyInfo = jsonPropertyInfo; state.Current.NumberHandling = jsonPropertyInfo.EffectiveNumberHandling; bool useExtensionProperty = dataExtKey != null; if (useExtensionProperty) { Debug.Assert(jsonPropertyInfo == state.Current.JsonTypeInfo.ExtensionDataProperty); state.Current.JsonPropertyNameAsString = dataExtKey; JsonSerializer.CreateExtensionDataProperty(obj, jsonPropertyInfo, options); } ReadPropertyValue(obj, ref state, ref tempReader, jsonPropertyInfo, useExtensionProperty); } FoundProperty[] toReturn = argumentState.FoundProperties !; argumentState.FoundProperties = null; ArrayPool <FoundProperty> .Shared.Return(toReturn, clearArray: true); } } else { // Slower path that supports continuation and metadata reads. if (state.Current.ObjectState == StackFrameObjectState.None) { if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.StartToken; } // Read any metadata properties. if (state.Current.CanContainMetadata && state.Current.ObjectState < StackFrameObjectState.ReadMetadata) { if (!JsonSerializer.TryReadMetadata(this, jsonTypeInfo, ref reader, ref state)) { value = default; return(false); } if (state.Current.MetadataPropertyNames == MetadataPropertyName.Ref) { value = JsonSerializer.ResolveReferenceId <T>(ref state); return(true); } state.Current.ObjectState = StackFrameObjectState.ReadMetadata; } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, options, ref state) is JsonConverter polymorphicConverter) { Debug.Assert(!IsValueType); bool success = polymorphicConverter.OnTryReadAsObject(ref reader, options, ref state, out object?objectResult); value = (T)objectResult !; state.ExitPolymorphicConverter(success); return(success); } // Handle metadata post polymorphic dispatch if (state.Current.ObjectState < StackFrameObjectState.ConstructorArguments) { 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); } BeginRead(ref state, ref reader, options); state.Current.ObjectState = StackFrameObjectState.ConstructorArguments; } if (!ReadConstructorArgumentsWithContinuation(ref state, ref reader, options)) { value = default; return(false); } obj = (T)CreateObject(ref state.Current); if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Id)) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); state.ReferenceResolver.AddReference(state.ReferenceId, obj); state.ReferenceId = null; } jsonTypeInfo.OnDeserializing?.Invoke(obj); if (argumentState.FoundPropertyCount > 0) { for (int i = 0; i < argumentState.FoundPropertyCount; i++) { JsonPropertyInfo jsonPropertyInfo = argumentState.FoundPropertiesAsync ![i].Item1;
protected override void Add(object?value, ref ReadStack state) { ((Action <TCollection, object?>)state.Current.AddMethodDelegate !)((TCollection)state.Current.ReturnValue !, value); }
/// <summary> /// When overridden, create the collection. It may be a temporary collection or the final collection. /// </summary> protected virtual void CreateCollection(ref ReadStack state) { }
internal override bool OnTryRead(ref BinaryReader reader, Type typeToConvert, BinarySerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { object obj; if (state.UseFastPath) { // 刚进入对象读取 if (reader.CurrentTypeInfo == null || reader.CurrentTypeInfo.SerializeType != ClassType.Object) { ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert); } reader.AheadReadStartToken(); if (state.Current.BinaryClassInfo.CreateObject == null) { ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(state.Current.BinaryClassInfo.Type, ref reader, ref state); } RefState refState = BinarySerializer.ReadReferenceForObject(this, ref state, ref reader, out object refValue); if (refState == RefState.None) { obj = state.Current.BinaryClassInfo.CreateObject(); state.ReferenceResolver.AddReferenceObject(state.Current.RefId, obj); } else { obj = refValue; } // Process all properties. while (true) { reader.AheadReadPropertyName(); BinaryPropertyInfo binaryPropertyInfo = null; state.Current.PropertyState = StackFramePropertyState.Name; if (reader.TokenType == BinaryTokenType.EndObject) { break; } Debug.Assert(reader.TokenType == BinaryTokenType.PropertyName); ushort propertySeq = reader.CurrentPropertySeq; BinaryMemberInfo mi = state.GetMemberInfo(propertySeq); // Debug.Assert(mi != null); binaryPropertyInfo = BinarySerializer.LookupProperty( obj, mi.NameAsUtf8Bytes, ref state, out bool useExtensionProperty); state.Current.UseExtensionProperty = useExtensionProperty; // binaryPropertyInfo = state.LookupProperty(mi.NameAsString); state.Current.BinaryPropertyInfo = binaryPropertyInfo; state.Current.PropertyPolymorphicConverter = null; if (binaryPropertyInfo == null) { if (!reader.TrySkip(options)) { value = default; return(false); } state.Current.EndProperty(); continue; } if (!binaryPropertyInfo.ShouldDeserialize) { if (!reader.TrySkip(options)) { state.Current.ReturnValue = obj; value = default; return(false); } state.Current.EndProperty(); continue; } // Obtain the CLR value from the Binary and set the member. if (!state.Current.UseExtensionProperty) { binaryPropertyInfo.ReadBinaryAndSetMember(obj, ref state, ref reader); } else { // TODO 扩展属性 } state.Current.EndProperty(); } } else { // Slower path that supports continuation and preserved references. if (state.Current.ObjectState == StackFrameObjectState.None) { // 刚进入对象读取 if (reader.CurrentTypeInfo == null || reader.CurrentTypeInfo.SerializeType != ClassType.Object) { ThrowHelper.ThrowBinaryException_DeserializeUnableToConvertValue(TypeToConvert); } if (!reader.ReadStartToken()) { value = default; return(false); } RefState refState = BinarySerializer.ReadReferenceForObject(this, ref state, ref reader, out object refValue); if (refState == RefState.None) { state.Current.ObjectState = StackFrameObjectState.StartToken; } else if (refState == RefState.Created) { state.Current.ObjectState = StackFrameObjectState.CreatedObject; state.Current.ReturnValue = refValue; } } // 创建对象 if (state.Current.ObjectState < StackFrameObjectState.CreatedObject) { if (state.Current.BinaryClassInfo.CreateObject == null) { ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(state.Current.BinaryClassInfo.Type, ref reader, ref state); } obj = state.Current.BinaryClassInfo.CreateObject(); state.ReferenceResolver.AddReferenceObject(state.Current.RefId, obj); state.Current.ReturnValue = obj; state.Current.ObjectState = StackFrameObjectState.CreatedObject; } else { obj = state.Current.ReturnValue !; Debug.Assert(obj != null); } // Process all properties. while (true) { // Determine the property. // 读取属性索引 if (state.Current.PropertyState == StackFramePropertyState.None) { if (!reader.ReadPropertyName()) { state.Current.ReturnValue = obj; value = default; return(false); } state.Current.PropertyState = StackFramePropertyState.ReadName; // } BinaryPropertyInfo binaryPropertyInfo; if (state.Current.PropertyState <= StackFramePropertyState.ReadName) { state.Current.PropertyState = StackFramePropertyState.Name; if (reader.TokenType == BinaryTokenType.EndObject) { break; } Debug.Assert(reader.TokenType == BinaryTokenType.PropertyName); ushort propertySeq = reader.CurrentPropertySeq; BinaryMemberInfo mi = state.GetMemberInfo(propertySeq); Debug.Assert(mi != null); binaryPropertyInfo = BinarySerializer.LookupProperty( obj, mi.NameAsUtf8Bytes, ref state, out bool useExtensionProperty); state.Current.UseExtensionProperty = useExtensionProperty; // binaryPropertyInfo = state.LookupProperty(mi.NameAsString); state.Current.BinaryPropertyInfo = binaryPropertyInfo; state.Current.PropertyPolymorphicConverter = null; if (binaryPropertyInfo == null) { state.Current.EndProperty(); continue; } } else { Debug.Assert(state.Current.BinaryPropertyInfo != null); binaryPropertyInfo = state.Current.BinaryPropertyInfo !; } if (state.Current.PropertyState < StackFramePropertyState.ReadValue) { if (!binaryPropertyInfo.ShouldDeserialize) { if (!reader.TrySkip(options)) { state.Current.ReturnValue = obj; value = default; return(false); } state.Current.EndProperty(); continue; } } if (state.Current.PropertyState < StackFramePropertyState.TryRead) { // Obtain the CLR value from the Binary and set the member. if (!state.Current.UseExtensionProperty) { if (!binaryPropertyInfo.ReadBinaryAndSetMember(obj, ref state, ref reader)) { state.Current.ReturnValue = obj; value = default; return(false); } } else { // TODO 扩展属性 } state.Current.EndProperty(); } } } // Check if we are trying to build the sorted cache. if (state.Current.PropertyRefCache != null) { state.Current.BinaryClassInfo.UpdateSortedPropertyCache(ref state.Current); } value = (T)obj; return(true); }
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T?value) => Converter.OnTryRead(ref reader, typeToConvert, options, ref state, out value);
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo; object obj; if (!state.SupportContinuation && !state.Current.CanContainMetadata) { // Fast path that avoids maintaining state variables and dealing with preserved references. 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); // Process all properties. while (true) { // Read the property name or EndObject. reader.ReadWithVerify(); JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.EndObject) { break; } // Read method would have thrown if otherwise. Debug.Assert(tokenType == JsonTokenType.PropertyName); ReadOnlySpan <byte> unescapedPropertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options); JsonPropertyInfo jsonPropertyInfo = JsonSerializer.LookupProperty( obj, unescapedPropertyName, ref state, options, out bool useExtensionProperty); ReadPropertyValue(obj, ref state, ref reader, jsonPropertyInfo, useExtensionProperty); } } else { // Slower path that supports continuation and reading metadata. if (state.Current.ObjectState == StackFrameObjectState.None) { if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.StartToken; } // Handle the metadata properties. if (state.Current.CanContainMetadata && state.Current.ObjectState < StackFrameObjectState.ReadMetadata) { if (!JsonSerializer.TryReadMetadata(this, jsonTypeInfo, ref reader, ref state)) { value = default; return(false); } if (state.Current.MetadataPropertyNames == MetadataPropertyName.Ref) { value = JsonSerializer.ResolveReferenceId <T>(ref state); return(true); } state.Current.ObjectState = StackFrameObjectState.ReadMetadata; } // Dispatch to any polymorphic converters: should always be entered regardless of ObjectState progress if (state.Current.MetadataPropertyNames.HasFlag(MetadataPropertyName.Type) && state.Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntryStarted && ResolvePolymorphicConverter(jsonTypeInfo, options, ref state) is JsonConverter polymorphicConverter) { Debug.Assert(!IsValueType); bool success = polymorphicConverter.OnTryReadAsObject(ref reader, options, ref state, out object?objectResult); value = (T)objectResult !; state.ExitPolymorphicConverter(success); return(success); } if (state.Current.ObjectState < StackFrameObjectState.CreatedObject) { 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)) { Debug.Assert(state.ReferenceId != null); Debug.Assert(options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve); state.ReferenceResolver.AddReference(state.ReferenceId, obj); state.ReferenceId = null; } jsonTypeInfo.OnDeserializing?.Invoke(obj); state.Current.ReturnValue = obj; state.Current.ObjectState = StackFrameObjectState.CreatedObject; } else { obj = state.Current.ReturnValue !; Debug.Assert(obj != null); } // Process all properties. while (true) { // Determine the property. if (state.Current.PropertyState == StackFramePropertyState.None) { state.Current.PropertyState = StackFramePropertyState.ReadName; if (!reader.Read()) { // The read-ahead functionality will do the Read(). state.Current.ReturnValue = obj; value = default; return(false); } } JsonPropertyInfo jsonPropertyInfo; if (state.Current.PropertyState < StackFramePropertyState.Name) { state.Current.PropertyState = StackFramePropertyState.Name; JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.EndObject) { break; } // Read method would have thrown if otherwise. Debug.Assert(tokenType == JsonTokenType.PropertyName); ReadOnlySpan <byte> unescapedPropertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options); jsonPropertyInfo = JsonSerializer.LookupProperty( obj, unescapedPropertyName, ref state, options, out bool useExtensionProperty); state.Current.UseExtensionProperty = useExtensionProperty; } else { Debug.Assert(state.Current.JsonPropertyInfo != null); jsonPropertyInfo = state.Current.JsonPropertyInfo !; } if (state.Current.PropertyState < StackFramePropertyState.ReadValue) { if (!jsonPropertyInfo.CanDeserialize) { if (!reader.TrySkip()) { state.Current.ReturnValue = obj; value = default; return(false); } state.Current.EndProperty(); continue; } if (!ReadAheadPropertyValue(ref state, ref reader, jsonPropertyInfo)) { state.Current.ReturnValue = obj; value = default; return(false); } } if (state.Current.PropertyState < StackFramePropertyState.TryRead) { // Obtain the CLR value from the JSON and set the member. if (!state.Current.UseExtensionProperty) { if (!jsonPropertyInfo.ReadJsonAndSetMember(obj, ref state, ref reader)) { state.Current.ReturnValue = obj; value = default; return(false); } } else { if (!jsonPropertyInfo.ReadJsonAndAddExtensionProperty(obj, ref state, ref reader)) { // No need to set 'value' here since JsonElement must be read in full. state.Current.ReturnValue = obj; value = default; return(false); } } state.Current.EndProperty(); } } } jsonTypeInfo.OnDeserialized?.Invoke(obj); // Unbox Debug.Assert(obj != null); value = (T)obj; // Check if we are trying to build the sorted cache. if (state.Current.PropertyRefCache != null) { jsonTypeInfo.UpdateSortedPropertyCache(ref state.Current); } return(true); }
protected abstract void CreateCollection(ref ReadStack state, JsonSerializerOptions options);
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out TOption?value) { // `null` values deserialize as `None` if (!state.IsContinuation && reader.TokenType == JsonTokenType.Null) { value = null; return(true); } state.Current.JsonPropertyInfo = state.Current.JsonTypeInfo.ElementTypeInfo !.PropertyInfoForTypeInfo; if (_elementConverter.TryRead(ref reader, typeof(TElement), options, ref state, out TElement? element)) { value = _optionConstructor(element); return(true); } value = null; return(false); }
internal override bool OnTryRead( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out TCollection value) { bool shouldReadPreservedReferences = options.ReferenceHandling.ShouldReadPreservedReferences(); if (!state.SupportContinuation && !shouldReadPreservedReferences) { // Fast path that avoids maintaining state variables and dealing with preserved references. if (reader.TokenType != JsonTokenType.StartArray) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } CreateCollection(ref state, options); JsonConverter <TElement> elementConverter = GetElementConverter(ref state); if (elementConverter.CanUseDirectReadOrWrite) { // Fast path that avoids validation and extra indirection. while (true) { reader.ReadWithVerify(); if (reader.TokenType == JsonTokenType.EndArray) { break; } // Obtain the CLR value from the JSON and apply to the object. TElement element = elementConverter.Read(ref reader, elementConverter.TypeToConvert, options); Add(element, ref state); } } else { // Process all elements. while (true) { reader.ReadWithVerify(); if (reader.TokenType == JsonTokenType.EndArray) { break; } // Get the value from the converter and add it. elementConverter.TryRead(ref reader, typeof(TElement), options, ref state, out TElement element); Add(element, ref state); } } } else { // Slower path that supports continuation and preserved references. if (state.Current.ObjectState == StackFrameObjectState.None) { if (reader.TokenType == JsonTokenType.StartArray) { state.Current.ObjectState = StackFrameObjectState.MetadataPropertyValue; } else if (shouldReadPreservedReferences) { if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.StartToken; } else { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } } // Handle the metadata properties. if (shouldReadPreservedReferences && state.Current.ObjectState < StackFrameObjectState.MetadataPropertyValue) { if (JsonSerializer.ResolveMetadata(this, ref reader, ref state)) { if (state.Current.ObjectState == StackFrameObjectState.MetadataRefPropertyEndObject) { value = (TCollection)state.Current.ReturnValue !; return(true); } } else { value = default !;
///// <summary> ///// Whether the converter is built-in and handles a number type. ///// </summary> //internal bool IsInternalConverterForNumberType; /// <summary> /// Loosely-typed ReadCore() that forwards to strongly-typed ReadCore(). /// </summary> internal abstract object ReadCoreAsObject(ref BinaryReader reader, BinarySerializerOptions options, ref ReadStack state);
internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { JsonTypeInfo jsonTypeInfo = state.Current.JsonTypeInfo; object obj; if (state.UseFastPath) { // Fast path that avoids maintaining state variables and dealing with preserved references. 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 !() !; // Process all properties. while (true) { // Read the property name or EndObject. reader.ReadWithVerify(); JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.EndObject) { break; } // Read method would have thrown if otherwise. Debug.Assert(tokenType == JsonTokenType.PropertyName); ReadOnlySpan <byte> unescapedPropertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options); JsonPropertyInfo jsonPropertyInfo = JsonSerializer.LookupProperty( obj, unescapedPropertyName, ref state, options, out bool useExtensionProperty); ReadPropertyValue(obj, ref state, ref reader, jsonPropertyInfo, useExtensionProperty); } } else { // Slower path that supports continuation and preserved references. if (state.Current.ObjectState == StackFrameObjectState.None) { if (reader.TokenType != JsonTokenType.StartObject) { ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert); } state.Current.ObjectState = StackFrameObjectState.StartToken; } // Handle the metadata properties. if (state.Current.ObjectState < StackFrameObjectState.PropertyValue) { if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve) { if (JsonSerializer.ResolveMetadataForJsonObject <T>(ref reader, ref state, options)) { if (state.Current.ObjectState == StackFrameObjectState.ReadRefEndObject) { // This will never throw since it was previously validated in ResolveMetadataForJsonObject. value = (T)state.Current.ReturnValue !; return(true); } } else { value = default; return(false); } } } if (state.Current.ObjectState < StackFrameObjectState.CreatedObject) { if (jsonTypeInfo.CreateObject == null) { ThrowHelper.ThrowNotSupportedException_DeserializeNoConstructor(jsonTypeInfo.Type, ref reader, ref state); } obj = jsonTypeInfo.CreateObject !() !; state.Current.ReturnValue = obj; state.Current.ObjectState = StackFrameObjectState.CreatedObject; } else { obj = state.Current.ReturnValue !; Debug.Assert(obj != null); } // Process all properties. while (true) { // Determine the property. if (state.Current.PropertyState == StackFramePropertyState.None) { state.Current.PropertyState = StackFramePropertyState.ReadName; if (!reader.Read()) { // The read-ahead functionality will do the Read(). state.Current.ReturnValue = obj; value = default; return(false); } } JsonPropertyInfo jsonPropertyInfo; if (state.Current.PropertyState < StackFramePropertyState.Name) { state.Current.PropertyState = StackFramePropertyState.Name; JsonTokenType tokenType = reader.TokenType; if (tokenType == JsonTokenType.EndObject) { break; } // Read method would have thrown if otherwise. Debug.Assert(tokenType == JsonTokenType.PropertyName); ReadOnlySpan <byte> unescapedPropertyName = JsonSerializer.GetPropertyName(ref state, ref reader, options); jsonPropertyInfo = JsonSerializer.LookupProperty( obj, unescapedPropertyName, ref state, options, out bool useExtensionProperty); state.Current.UseExtensionProperty = useExtensionProperty; } else { Debug.Assert(state.Current.JsonPropertyInfo != null); jsonPropertyInfo = state.Current.JsonPropertyInfo !; } if (state.Current.PropertyState < StackFramePropertyState.ReadValue) { if (!jsonPropertyInfo.ShouldDeserialize) { if (!reader.TrySkip()) { state.Current.ReturnValue = obj; value = default; return(false); } state.Current.EndProperty(); continue; } if (!ReadAheadPropertyValue(ref state, ref reader, jsonPropertyInfo)) { state.Current.ReturnValue = obj; value = default; return(false); } } if (state.Current.PropertyState < StackFramePropertyState.TryRead) { // Obtain the CLR value from the JSON and set the member. if (!state.Current.UseExtensionProperty) { if (!jsonPropertyInfo.ReadJsonAndSetMember(obj, ref state, ref reader)) { state.Current.ReturnValue = obj; value = default; return(false); } } else { if (!jsonPropertyInfo.ReadJsonAndAddExtensionProperty(obj, ref state, ref reader)) { // No need to set 'value' here since JsonElement must be read in full. state.Current.ReturnValue = obj; value = default; return(false); } } state.Current.EndProperty(); } } } // Check if we are trying to build the sorted cache. if (state.Current.PropertyRefCache != null) { jsonTypeInfo.UpdateSortedPropertyCache(ref state.Current); } value = (T)obj; return(true); }
internal sealed override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNullWhen(false)] out T value) { object obj; if (state.UseFastPath) { // Fast path that avoids maintaining state variables. ReadOnlySpan <byte> originalSpan = reader.OriginalSpan; ReadConstructorArguments(ref state, ref reader, options); obj = CreateObject(ref state.Current); if (state.Current.PropertyIndex > 0) { Utf8JsonReader tempReader; for (int i = 0; i < state.Current.PropertyIndex; i++) { JsonPropertyInfo jsonPropertyInfo = state.Current.CtorArgumentState !.FoundProperties ![i].Item1;