private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary);

            if (state.Current.IsProcessingEnumerable)
            {
                // A nested object within an enumerable.
                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object.
                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (classInfo.CreateObject is null && classInfo.ClassType == ClassType.Object)
            {
                if (classInfo.Type.IsInterface)
                {
                    ThrowHelper.ThrowInvalidOperationException_DeserializePolymorphicInterface(classInfo.Type);
                }
                else
                {
                    ThrowHelper.ThrowInvalidOperationException_DeserializeMissingParameterlessConstructor(classInfo.Type);
                }
            }

            state.Current.ReturnValue = classInfo.CreateObject();
        }
        private static void HandleStartObject(JsonSerializerOptions options, ref ReadStack state)
        {
            if (state.Current.Skip())
            {
                state.Push();
                state.Current.Drain = true;
                return;
            }

            if (state.Current.IsEnumerable() || state.Current.IsPropertyEnumerable())
            {
                // An array of objects either on the current property or on a list
                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.JsonClassInfo = options.GetOrAddClass(objType);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object
                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.JsonClassInfo = options.GetOrAddClass(objType);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            state.Current.ReturnValue = classInfo.CreateObject();
        }
Esempio n. 3
0
        private static void HandleStartArray(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack state)
        {
            if (state.Current.Skip())
            {
                // The array is not being applied to the object.
                state.Push();
                state.Current.Drain = true;
                return;
            }

            Type arrayType = state.Current.JsonPropertyInfo.PropertyType;

            if (!typeof(IEnumerable).IsAssignableFrom(arrayType) || (arrayType.IsArray && arrayType.GetArrayRank() > 1))
            {
                ThrowHelper.ThrowJsonReaderException_DeserializeUnableToConvertValue(arrayType, reader, state);
            }

            Debug.Assert(state.Current.IsPropertyEnumerable());
            if (state.Current.IsPropertyEnumerable())
            {
                if (state.Current.EnumerableCreated)
                {
                    // A nested json array so push a new stack frame.
                    Type elementType = state.Current.JsonClassInfo.ElementClassInfo.GetPolicyProperty().PropertyType;

                    state.Push();

                    state.Current.JsonClassInfo      = options.GetOrAddClass(elementType);
                    state.Current.JsonPropertyInfo   = state.Current.JsonClassInfo.GetPolicyProperty();
                    state.Current.PopStackOnEndArray = true;
                }
                else
                {
                    state.Current.EnumerableCreated = true;
                }

                // If current property is already set (from a constructor, for example) leave as-is
                if (state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue, options) == null)
                {
                    // Create the enumerable.
                    object value = ReadStackFrame.CreateEnumerableValue(ref reader, ref state, options);
                    if (value != null)
                    {
                        if (state.Current.ReturnValue != null)
                        {
                            state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value, options);
                        }
                        else
                        {
                            // Primitive arrays being returned without object
                            state.Current.SetReturnValue(value, options);
                        }
                    }
                }
            }
        }
        private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            if (state.Current.Skip())
            {
                state.Push();
                state.Current.Drain = true;
                return;
            }

            if (state.Current.IsProcessingEnumerable)
            {
                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                if (state.Current.IsDictionary)
                {
                    // Verify that the Dictionary can be deserialized by having <string> as first generic argument.
                    Debug.Assert(state.Current.JsonClassInfo.Type.GetGenericArguments().Length >= 1);
                    if (state.Current.JsonClassInfo.Type.GetGenericArguments()[0].UnderlyingSystemType != typeof(string))
                    {
                        ThrowHelper.ThrowJsonReaderException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, reader, state);
                    }

                    ClassType classType = state.Current.JsonClassInfo.ElementClassInfo.ClassType;

                    if (state.Current.ReturnValue == null)
                    {
                        // The Dictionary created below will be returned to corresponding Parse() etc method.
                        // Ensure any nested array creates a new frame.
                        state.Current.EnumerableCreated = true;
                    }
                    else
                    {
                        Debug.Assert(classType == ClassType.Object || classType == ClassType.Dictionary);

                        // A nested object or dictionary.
                        JsonClassInfo classInfoTemp = state.Current.JsonClassInfo;
                        state.Push();
                        state.Current.JsonClassInfo = classInfoTemp.ElementClassInfo;
                        state.Current.InitializeJsonPropertyInfo();
                    }
                }
                else
                {
                    // Nested object.
                    Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                    state.Push();
                    state.Current.Initialize(objType, options);
                }
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            state.Current.ReturnValue = classInfo.CreateObject();
        }
Esempio n. 5
0
        private static void HandleStartDictionary(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingEnumerable);

            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            if (jsonPropertyInfo == null)
            {
                jsonPropertyInfo = state.Current.JsonClassInfo.CreateRootObject(options);
            }

            Debug.Assert(jsonPropertyInfo != null);

            // A nested object or dictionary so push new frame.
            if (state.Current.PropertyInitialized)
            {
                Debug.Assert(state.Current.IsDictionary);

                JsonClassInfo classInfoTemp = state.Current.JsonClassInfo;
                state.Push();
                state.Current.JsonClassInfo = classInfoTemp.ElementClassInfo;
                state.Current.InitializeJsonPropertyInfo();

                ClassType classType = state.Current.JsonClassInfo.ClassType;
                if (classType == ClassType.Value &&
                    jsonPropertyInfo.ElementClassInfo.Type != typeof(object) &&
                    jsonPropertyInfo.ElementClassInfo.Type != typeof(JsonElement))
                {
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, reader, state.PropertyPath);
                }

                JsonClassInfo classInfo = state.Current.JsonClassInfo;
                state.Current.ReturnValue = classInfo.CreateObject();
                return;
            }

            state.Current.PropertyInitialized = true;

            // If current property is already set (from a constructor, for example) leave as-is.
            if (jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue) == null)
            {
                // Create the dictionary.
                JsonClassInfo dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.RuntimePropertyType);
                IDictionary   value = (IDictionary)dictionaryClassInfo.CreateObject();
                if (value != null)
                {
                    if (state.Current.ReturnValue != null)
                    {
                        state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value);
                    }
                    else
                    {
                        // A dictionary is being returned directly, or a nested dictionary.
                        state.Current.SetReturnValue(value);
                    }
                }
            }
        }
Esempio n. 6
0
        private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary);

            if (state.Current.IsProcessingEnumerable)
            {
                // A nested object within an enumerable.
                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object.
                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            state.Current.ReturnValue = classInfo.CreateObject();
        }
Esempio n. 7
0
        internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T?value)
        {
            if (ConverterStrategy == ConverterStrategy.Value)
            {
                // A value converter should never be within a continuation.
                Debug.Assert(!state.IsContinuation);

                // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    value = default;
                    return(true);
                }

#if !DEBUG
                // For performance, only perform validation on internal converters on debug builds.
                if (IsInternalConverter)
                {
                    if (state.Current.NumberHandling != null)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }
                }
                else
#endif
                {
                    JsonTokenType originalPropertyTokenType     = reader.TokenType;
                    int           originalPropertyDepth         = reader.CurrentDepth;
                    long          originalPropertyBytesConsumed = reader.BytesConsumed;

                    if (state.Current.NumberHandling != null)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }

                    VerifyRead(
                        originalPropertyTokenType,
                        originalPropertyDepth,
                        originalPropertyBytesConsumed,
                        isValueConverter: true,
                        ref reader);
                }

                if (options.ReferenceHandlingStrategy == ReferenceHandlingStrategy.Preserve &&
                    CanBePolymorphic && value is JsonElement element)
                {
                    // Edge case where we want to lookup for a reference when parsing into typeof(object)
                    // instead of return `value` as a JsonElement.
                    Debug.Assert(TypeToConvert == typeof(object));

                    if (JsonSerializer.TryGetReferenceFromJsonElement(ref state, element, out object?referenceValue))
                    {
                        value = (T?)referenceValue;
                    }
                }

                return(true);
            }

            bool success;

            // Remember if we were a continuation here since Push() may affect IsContinuation.
            bool wasContinuation = state.IsContinuation;

#if DEBUG
            // DEBUG: ensure push/pop operations preserve stack integrity
            JsonTypeInfo originalJsonTypeInfo = state.Current.JsonTypeInfo;
#endif
            state.Push();
            Debug.Assert(TypeToConvert.IsAssignableFrom(state.Current.JsonTypeInfo.Type));

#if !DEBUG
            // For performance, only perform validation on internal converters on debug builds.
            if (IsInternalConverter)
            {
                if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead && !wasContinuation)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    value   = default;
                    success = true;
                }
                else
                {
                    success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                }
            }
            else
#endif
            {
                if (!wasContinuation)
                {
                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead)
                    {
                        if (!CanBeNull)
                        {
                            ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                        }

                        value = default;
                        state.Pop(true);
#if DEBUG
                        Debug.Assert(ReferenceEquals(originalJsonTypeInfo, state.Current.JsonTypeInfo));
#endif
                        return(true);
                    }

                    Debug.Assert(state.Current.OriginalTokenType == JsonTokenType.None);
                    state.Current.OriginalTokenType = reader.TokenType;

                    Debug.Assert(state.Current.OriginalDepth == 0);
                    state.Current.OriginalDepth = reader.CurrentDepth;
                }

                success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                if (success)
                {
                    if (state.IsContinuation)
                    {
                        // The resumable converter did not forward to the next converter that previously returned false.
                        ThrowHelper.ThrowJsonException_SerializationConverterRead(this);
                    }

                    VerifyRead(
                        state.Current.OriginalTokenType,
                        state.Current.OriginalDepth,
                        bytesConsumed: 0,
                        isValueConverter: false,
                        ref reader);

                    // No need to clear state.Current.* since a stack pop will occur.
                }
            }

            state.Pop(success);
#if DEBUG
            Debug.Assert(ReferenceEquals(originalJsonTypeInfo, state.Current.JsonTypeInfo));
#endif
            return(success);
        }
Esempio n. 8
0
        internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, [MaybeNull] out T value)
        {
            if (ClassType == ClassType.Value)
            {
                // A value converter should never be within a continuation.
                Debug.Assert(!state.IsContinuation);

                // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                if (reader.TokenType == JsonTokenType.Null && !HandleNull)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    value = default;
                    return(true);
                }

#if !DEBUG
                // For performance, only perform validation on internal converters on debug builds.
                if (IsInternalConverter)
                {
                    value = Read(ref reader, typeToConvert, options);
                }
                else
#endif
                {
                    JsonTokenType originalPropertyTokenType     = reader.TokenType;
                    int           originalPropertyDepth         = reader.CurrentDepth;
                    long          originalPropertyBytesConsumed = reader.BytesConsumed;

                    value = Read(ref reader, typeToConvert, options);
                    VerifyRead(
                        originalPropertyTokenType,
                        originalPropertyDepth,
                        originalPropertyBytesConsumed,
                        isValueConverter: true,
                        ref reader);
                }

                return(true);
            }

            bool success;

            // Remember if we were a continuation here since Push() may affect IsContinuation.
            bool wasContinuation = state.IsContinuation;

            state.Push();

#if !DEBUG
            // For performance, only perform validation on internal converters on debug builds.
            if (IsInternalConverter)
            {
                if (reader.TokenType == JsonTokenType.Null && !HandleNull && !wasContinuation)
                {
                    if (!CanBeNull)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                    }

                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    value   = default;
                    success = true;
                }
                else
                {
                    success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                }
            }
            else
#endif
            {
                if (!wasContinuation)
                {
                    // For perf and converter simplicity, handle null here instead of forwarding to the converter.
                    if (reader.TokenType == JsonTokenType.Null && !HandleNull)
                    {
                        if (!CanBeNull)
                        {
                            ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                        }

                        value = default;
                        state.Pop(true);
                        return(true);
                    }

                    Debug.Assert(state.Current.OriginalTokenType == JsonTokenType.None);
                    state.Current.OriginalTokenType = reader.TokenType;

                    Debug.Assert(state.Current.OriginalDepth == 0);
                    state.Current.OriginalDepth = reader.CurrentDepth;
                }

                success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
                if (success)
                {
                    if (state.IsContinuation)
                    {
                        // The resumable converter did not forward to the next converter that previously returned false.
                        ThrowHelper.ThrowJsonException_SerializationConverterRead(this);
                    }

                    VerifyRead(
                        state.Current.OriginalTokenType,
                        state.Current.OriginalDepth,
                        bytesConsumed: 0,
                        isValueConverter: false,
                        ref reader);

                    // No need to clear state.Current.* since a stack pop will occur.
                }
            }

            state.Pop(success);
            return(success);
        }
        private static void HandleStartArray(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack state)
        {
            JsonPropertyInfo jsonPropertyInfo;

            jsonPropertyInfo = state.Current.JsonPropertyInfo;

            bool skip = jsonPropertyInfo != null && !jsonPropertyInfo.ShouldDeserialize;

            if (skip || state.Current.Skip())
            {
                // The array is not being applied to the object.
                state.Push();
                state.Current.Drain = true;
                return;
            }

            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);
            }

            Type arrayType = jsonPropertyInfo.RuntimePropertyType;

            if (!typeof(IEnumerable).IsAssignableFrom(arrayType) || (arrayType.IsArray && arrayType.GetArrayRank() > 1))
            {
                ThrowHelper.ThrowJsonReaderException_DeserializeUnableToConvertValue(arrayType, reader, state);
            }

            Debug.Assert(state.Current.IsPropertyEnumerable || state.Current.IsDictionary);

            if (state.Current.EnumerableCreated)
            {
                // A nested json array so push a new stack frame.
                Type elementType = state.Current.JsonClassInfo.ElementClassInfo.GetPolicyProperty().RuntimePropertyType;

                state.Push();

                state.Current.Initialize(elementType, options);
                state.Current.PopStackOnEnd = true;
            }
            else
            {
                state.Current.EnumerableCreated = true;
            }

            jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If current property is already set (from a constructor, for example) leave as-is.
            if (jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue) == null)
            {
                // Create the enumerable.
                object value = ReadStackFrame.CreateEnumerableValue(ref reader, ref state, options);
                if (value != null)
                {
                    if (state.Current.ReturnValue != null)
                    {
                        state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value);
                    }
                    else
                    {
                        // Primitive arrays being returned without object
                        state.Current.SetReturnValue(value);
                    }
                }
            }
        }
Esempio n. 10
0
        internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, ref ReadStack state, out T?value)
        {
            // For perf and converter simplicity, handle null here instead of forwarding to the converter.
            if (reader.TokenType == JsonTokenType.Null && !HandleNullOnRead && !state.IsContinuation)
            {
                if (default(T) is not null)
                {
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(TypeToConvert);
                }

                value = default;
                return(true);
            }

            if (ConverterStrategy == ConverterStrategy.Value)
            {
                // A value converter should never be within a continuation.
                Debug.Assert(!state.IsContinuation);
#if !DEBUG
                // For performance, only perform validation on internal converters on debug builds.
                if (IsInternalConverter)
                {
                    if (state.Current.NumberHandling != null && IsInternalConverterForNumberType)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }
                }
                else
#endif
                {
                    JsonTokenType originalPropertyTokenType     = reader.TokenType;
                    int           originalPropertyDepth         = reader.CurrentDepth;
                    long          originalPropertyBytesConsumed = reader.BytesConsumed;

                    if (state.Current.NumberHandling != null && IsInternalConverterForNumberType)
                    {
                        value = ReadNumberWithCustomHandling(ref reader, state.Current.NumberHandling.Value, options);
                    }
                    else
                    {
                        value = Read(ref reader, typeToConvert, options);
                    }

                    VerifyRead(
                        originalPropertyTokenType,
                        originalPropertyDepth,
                        originalPropertyBytesConsumed,
                        isValueConverter: true,
                        ref reader);
                }

                return(true);
            }

            Debug.Assert(IsInternalConverter);
            bool isContinuation = state.IsContinuation;
            bool success;

#if DEBUG
            // DEBUG: ensure push/pop operations preserve stack integrity
            JsonTypeInfo originalJsonTypeInfo = state.Current.JsonTypeInfo;
#endif
            state.Push();
            Debug.Assert(TypeToConvert == state.Current.JsonTypeInfo.Type);

#if DEBUG
            // For performance, only perform validation on internal converters on debug builds.
            if (!isContinuation)
            {
                Debug.Assert(state.Current.OriginalTokenType == JsonTokenType.None);
                state.Current.OriginalTokenType = reader.TokenType;

                Debug.Assert(state.Current.OriginalDepth == 0);
                state.Current.OriginalDepth = reader.CurrentDepth;
            }
#endif
            success = OnTryRead(ref reader, typeToConvert, options, ref state, out value);
#if DEBUG
            if (success)
            {
                if (state.IsContinuation)
                {
                    // The resumable converter did not forward to the next converter that previously returned false.
                    ThrowHelper.ThrowJsonException_SerializationConverterRead(this);
                }

                VerifyRead(
                    state.Current.OriginalTokenType,
                    state.Current.OriginalDepth,
                    bytesConsumed: 0,
                    isValueConverter: false,
                    ref reader);

                // No need to clear state.Current.* since a stack pop will occur.
            }
#endif

            state.Pop(success);
#if DEBUG
            Debug.Assert(ReferenceEquals(originalJsonTypeInfo, state.Current.JsonTypeInfo));
#endif
            return(success);
        }
Esempio n. 11
0
        private static void ReadCore(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack readStack)
        {
            try
            {
                JsonReaderState initialState = default;

                while (true)
                {
                    if (options.ReadAhead)
                    {
                        // When we're reading ahead we always have to save the state
                        // as we don't know if the next token is an opening object or
                        // array brace.
                        initialState = reader.CurrentState;
                    }

                    if (!reader.Read())
                    {
                        // Need more data
                        break;
                    }

                    JsonTokenType tokenType = reader.TokenType;

                    if (JsonHelpers.IsInRangeInclusive(tokenType, JsonTokenType.String, JsonTokenType.False))
                    {
                        Debug.Assert(tokenType == JsonTokenType.String || tokenType == JsonTokenType.Number || tokenType == JsonTokenType.True || tokenType == JsonTokenType.False);

                        HandleValue(tokenType, options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.PropertyName)
                    {
                        HandlePropertyName(options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.StartObject)
                    {
                        if (readStack.Current.SkipProperty)
                        {
                            readStack.Push();
                            readStack.Current.Drain = true;
                        }
                        else if (readStack.Current.IsProcessingValue)
                        {
                            if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState))
                            {
                                // Need more data
                                break;
                            }
                        }
                        else if (readStack.Current.IsProcessingDictionary)
                        {
                            HandleStartDictionary(options, ref reader, ref readStack);
                        }
                        else
                        {
                            HandleStartObject(options, ref reader, ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.EndObject)
                    {
                        if (readStack.Current.Drain)
                        {
                            readStack.Pop();
                        }
                        else if (readStack.Current.IsProcessingDictionary)
                        {
                            HandleEndDictionary(options, ref reader, ref readStack);
                        }
                        else
                        {
                            HandleEndObject(options, ref reader, ref readStack);
                        }
                    }
                    else if (tokenType == JsonTokenType.StartArray)
                    {
                        if (!readStack.Current.IsProcessingValue)
                        {
                            HandleStartArray(options, ref reader, ref readStack);
                        }
                        else if (!HandleObjectAsValue(tokenType, options, ref reader, ref readStack, ref initialState))
                        {
                            // Need more data
                            break;
                        }
                    }
                    else if (tokenType == JsonTokenType.EndArray)
                    {
                        HandleEndArray(options, ref reader, ref readStack);
                    }
                    else if (tokenType == JsonTokenType.Null)
                    {
                        HandleNull(ref reader, ref readStack, options);
                    }
                }
            }
            catch (JsonReaderException e)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(e, readStack.JsonPath);
            }

            readStack.BytesConsumed += reader.BytesConsumed;
            return;
        }
Esempio n. 12
0
        private static void ReadCore(
            JsonSerializerOptions options,
            ref Utf8JsonReader reader,
            ref ReadStack state)
        {
            try
            {
                while (reader.Read())
                {
                    JsonTokenType tokenType = reader.TokenType;

                    if (JsonHelpers.IsInRangeInclusive(tokenType, JsonTokenType.String, JsonTokenType.False))
                    {
                        Debug.Assert(tokenType == JsonTokenType.String || tokenType == JsonTokenType.Number || tokenType == JsonTokenType.True || tokenType == JsonTokenType.False);

                        if (HandleValue(tokenType, options, ref reader, ref state))
                        {
                            continue;
                        }
                    }
                    else if (tokenType == JsonTokenType.PropertyName)
                    {
                        HandlePropertyName(options, ref reader, ref state);
                    }
                    else if (tokenType == JsonTokenType.StartObject)
                    {
                        if (state.Current.SkipProperty)
                        {
                            state.Push();
                            state.Current.Drain = true;
                        }
                        else if (state.Current.IsProcessingValue)
                        {
                            if (HandleValue(tokenType, options, ref reader, ref state))
                            {
                                continue;
                            }
                        }
                        else if (state.Current.IsProcessingDictionary)
                        {
                            HandleStartDictionary(options, ref reader, ref state);
                        }
                        else
                        {
                            HandleStartObject(options, ref reader, ref state);
                        }
                    }
                    else if (tokenType == JsonTokenType.EndObject)
                    {
                        if (state.Current.Drain)
                        {
                            state.Pop();
                        }
                        else if (state.Current.IsProcessingDictionary)
                        {
                            HandleEndDictionary(options, ref reader, ref state);
                        }
                        else
                        {
                            HandleEndObject(options, ref reader, ref state);
                        }
                    }
                    else if (tokenType == JsonTokenType.StartArray)
                    {
                        if (!state.Current.IsProcessingValue)
                        {
                            HandleStartArray(options, ref reader, ref state);
                        }
                        else if (HandleValue(tokenType, options, ref reader, ref state))
                        {
                            continue;
                        }
                    }
                    else if (tokenType == JsonTokenType.EndArray)
                    {
                        if (HandleEndArray(options, ref reader, ref state))
                        {
                            continue;
                        }
                    }
                    else if (tokenType == JsonTokenType.Null)
                    {
                        if (HandleNull(ref reader, ref state, options))
                        {
                            continue;
                        }
                    }
                }
            }
            catch (JsonReaderException e)
            {
                // Re-throw with Path information.
                ThrowHelper.ReThrowWithPath(e, state.PropertyPath);
            }

            return;
        }