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);
        }
Пример #2
0
 protected virtual void ConvertCollection(ref ReadStack state, JsonSerializerOptions options)
 {
 }
Пример #3
0
 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 !;
Пример #5
0
 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);
Пример #8
0
 protected override void CreateCollection(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
 {
     state.Current.ReturnValue = new List <TElement>();
 }
Пример #9
0
        protected override void ConvertCollection(ref ReadStack state, JsonSerializerOptions options)
        {
            List <TElement> list = (List <TElement>)state.Current.ReturnValue !;

            state.Current.ReturnValue = list.ToArray();
        }
Пример #10
0
        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;
        }
Пример #11
0
 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)
 {
 }
Пример #18
0
        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);
        }
Пример #19
0
        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;
Пример #20
0
 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)
 {
 }
Пример #22
0
        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);
Пример #24
0
        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);
        }
Пример #25
0
 protected abstract void CreateCollection(ref ReadStack state, JsonSerializerOptions options);
Пример #26
0
        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);
        }
Пример #27
0
        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);
Пример #29
0
        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);
        }
Пример #30
0
        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;