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

            // Note: unless we are a root object, we are going to push a property onto the ReadStack
            // in the if/else if check below.

            if (state.Current.IsProcessingEnumerable())
            {
                // A nested object within an enumerable (non-dictionary).
                HandleStartObjectInEnumerable(ref state, options, state.Current.JsonPropertyInfo !.DeclaredPropertyType);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object within an object.
                Debug.Assert(state.Current.IsProcessingObject(ClassType.Object));

                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo !;

            Debug.Assert(state.Current.IsProcessingObject(ClassType.Dictionary) || state.Current.IsProcessingObject(ClassType.Object) || state.Current.IsProcessingObject(ClassType.Enumerable));

            if (state.Current.IsProcessingObject(ClassType.Dictionary))
            {
                object?value = ReadStackFrame.CreateDictionaryValue(ref state);

                // If value is not null, then we don't have a converter so apply the value.
                if (value != null)
                {
                    state.Current.ReturnValue = value;
                    state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                }

                state.Current.CollectionPropertyInitialized = true;
            }
            else if (state.Current.IsProcessingObject(ClassType.Object))
            {
                if (classInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(classInfo.Type);
                }

                state.Current.ReturnValue = classInfo.CreateObject();
            }
            else if (state.Current.IsProcessingObject(ClassType.Enumerable))
            {
                // Nested array with metadata within another array with metadata.
                HandleStartObjectInEnumerable(ref state, options, classInfo.Type);

                Debug.Assert(options.ReferenceHandling.ShouldReadPreservedReferences());
                Debug.Assert(state.Current.JsonClassInfo !.Type.GetGenericTypeDefinition() == typeof(JsonPreservableArrayReference <>));

                state.Current.ReturnValue            = state.Current.JsonClassInfo.CreateObject !();
                state.Current.IsNestedPreservedArray = true;
            }
        }
        private static void HandleStartObject(JsonSerializerOptions options, 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);
                }
            }

            if (state.Current.IsProcessingObject(ClassType.Dictionary))
            {
                object value = ReadStackFrame.CreateDictionaryValue(ref state);

                // If value is not null, then we don't have a converter so apply the value.
                if (value != null)
                {
                    state.Current.ReturnValue = value;
                    state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                }

                state.Current.CollectionPropertyInitialized = true;
            }
            else
            {
                state.Current.ReturnValue = classInfo.CreateObject();
            }
        }
Example #3
0
        private static void HandleStartObject(JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary());

            // Note: unless we are a root object, we are going to push a property onto the ReadStack
            // in the if/else if check below.

            if (state.Current.IsProcessingEnumerable())
            {
                // A nested object within an enumerable (non-dictionary).

                if (!state.Current.CollectionPropertyInitialized)
                {
                    // We have bad JSON: enumerable element appeared without preceding StartArray token.
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonPropertyInfo.DeclaredPropertyType);
                }

                Type objType = state.Current.GetElementType();
                state.Push();
                state.Current.Initialize(objType, options);
            }
            else if (state.Current.JsonPropertyInfo != null)
            {
                // Nested object within an object.
                Debug.Assert(state.Current.IsProcessingObject(ClassType.Object));

                Type objType = state.Current.JsonPropertyInfo.RuntimePropertyType;
                state.Push();
                state.Current.Initialize(objType, options);
            }

            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            if (state.Current.IsProcessingObject(ClassType.Dictionary))
            {
                object value = ReadStackFrame.CreateDictionaryValue(ref state);

                // If value is not null, then we don't have a converter so apply the value.
                if (value != null)
                {
                    state.Current.ReturnValue = value;
                    state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                }

                state.Current.CollectionPropertyInitialized = true;
            }
            else if (state.Current.IsProcessingObject(ClassType.Object))
            {
                if (classInfo.CreateObject == null)
                {
                    ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(classInfo.Type);
                }

                state.Current.ReturnValue = classInfo.CreateObject();
            }
            else
            {
                // Only dictionaries or objects are valid given the `StartObject` token.
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type);
            }
        }
        private static void HandleStartDictionary(JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingEnumerable());

            JsonPropertyInfo?jsonPropertyInfo = state.Current.JsonPropertyInfo;

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

            Debug.Assert(jsonPropertyInfo != null);

            // A nested object or dictionary, so push new frame.
            if (state.Current.CollectionPropertyInitialized)
            {
                state.Push();
                state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo !;
                state.Current.InitializeJsonPropertyInfo();

                JsonClassInfo classInfo = state.Current.JsonClassInfo;

                if (state.Current.IsProcessingDictionary())
                {
                    object?dictValue = ReadStackFrame.CreateDictionaryValue(ref state);

                    // If value is not null, then we don't have a converter so apply the value.
                    if (dictValue != null)
                    {
                        state.Current.ReturnValue = dictValue;
                        state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                    }

                    state.Current.CollectionPropertyInitialized = true;
                }
                else if (state.Current.IsProcessingObject(ClassType.Object))
                {
                    if (classInfo.CreateObject == null)
                    {
                        ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(classInfo.Type);
                    }

                    state.Current.ReturnValue = classInfo.CreateObject();
                }
                else
                {
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type);
                }

                return;
            }

            state.Current.CollectionPropertyInitialized = true;

            object?value = ReadStackFrame.CreateDictionaryValue(ref state);

            if (value != null)
            {
                state.Current.DetermineIfDictionaryCanBePopulated(value);

                if (state.Current.ReturnValue != null)
                {
                    Debug.Assert(state.Current.JsonPropertyInfo != null);
                    state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value);
                }
                else
                {
                    // A dictionary is being returned directly, or a nested dictionary.
                    state.Current.ReturnValue = value;
                }
            }
        }
Example #5
0
        private static void HandleStartDictionary(JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingEnumerable());

            JsonPropertyInfo?jsonPropertyInfo = state.Current.JsonPropertyInfo;

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

            Debug.Assert(jsonPropertyInfo != null);

            // A nested object or dictionary, so push new frame.
            if (state.Current.CollectionPropertyInitialized)
            {
                state.Push();
                state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo !;
                state.Current.InitializeJsonPropertyInfo();

                JsonClassInfo classInfo = state.Current.JsonClassInfo;

                Debug.Assert(state.Current.IsProcessingDictionary() || state.Current.IsProcessingObject(ClassType.Object) || state.Current.IsProcessingObject(ClassType.Enumerable));

                if (state.Current.IsProcessingDictionary())
                {
                    object?dictValue = ReadStackFrame.CreateDictionaryValue(ref state);

                    // If value is not null, then we don't have a converter so apply the value.
                    if (dictValue != null)
                    {
                        state.Current.ReturnValue = dictValue;
                        state.Current.DetermineIfDictionaryCanBePopulated(state.Current.ReturnValue);
                    }

                    state.Current.CollectionPropertyInitialized = true;
                }
                else if (state.Current.IsProcessingObject(ClassType.Object))
                {
                    if (classInfo.CreateObject == null)
                    {
                        ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(classInfo.Type);
                    }

                    state.Current.ReturnValue = classInfo.CreateObject();
                }
                else if (state.Current.IsProcessingObject(ClassType.Enumerable))
                {
                    // Array with metadata within the dictionary.
                    HandleStartObjectInEnumerable(ref state, options, classInfo.Type);

                    Debug.Assert(options.ReferenceHandling.ShouldReadPreservedReferences());
                    Debug.Assert(state.Current.JsonClassInfo !.Type.GetGenericTypeDefinition() == typeof(JsonPreservableArrayReference <>));

                    state.Current.ReturnValue = state.Current.JsonClassInfo.CreateObject !();
                }

                return;
            }

            state.Current.CollectionPropertyInitialized = true;

            object?value = ReadStackFrame.CreateDictionaryValue(ref state);

            if (value != null)
            {
                state.Current.DetermineIfDictionaryCanBePopulated(value);

                if (state.Current.ReturnValue != null)
                {
                    Debug.Assert(state.Current.JsonPropertyInfo != null);
                    state.Current.JsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, value);
                }
                else
                {
                    // A dictionary is being returned directly, or a nested dictionary.
                    state.Current.ReturnValue = value;
                }
            }
        }