コード例 #1
0
        private static void HandleStartObject(JsonSerializerOptions options, ref Utf8JsonReader reader, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionary && !state.Current.IsProcessingIDictionaryConstructible);

            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.IsProcessingIDictionaryConstructible)
            {
                state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateObject();
            }
            else if (state.Current.JsonClassInfo.ClassType == ClassType.Value)
            {
                // Custom converter.
                state.Current.JsonPropertyInfo.Read(JsonTokenType.StartObject, ref state, ref reader);
                HandleEndObject(options, ref reader, ref state);
            }
            else
            {
                state.Current.ReturnValue = classInfo.CreateObject();
            }
        }
コード例 #2
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).
                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;
            }
        }
コード例 #3
0
        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();
            }
        }
コード例 #4
0
        public static object CreateEnumerableValue(ref ReadStack state)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList         converterList;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = elementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                // Clear the value if present to ensure we don't confuse tempEnumerableValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy &&
                    !state.Current.JsonPropertyInfo.IsImmutableArray)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject != null)
            {
                return(runtimeClassInfo.CreateObject());
            }
            else
            {
                // Could not create an instance to be returned. For derived types, this means there is no parameterless ctor.
                throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection(
                          jsonPropertyInfo.DeclaredPropertyType,
                          jsonPropertyInfo.ParentClassType,
                          jsonPropertyInfo.PropertyInfo);
            }
        }
コード例 #5
0
ファイル: ReadStackFrame.cs プロジェクト: twinkleeee/runtime
        public static object?CreateDictionaryValue(ref ReadStack state)
        {
            Debug.Assert(state.Current.JsonPropertyInfo != null);
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has a DictionaryConverter, then we use tempDictionaryValues.
            if (jsonPropertyInfo.DictionaryConverter != null)
            {
                IDictionary   converterDictionary;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo !;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterDictionary = elementClassInfo.PolicyProperty !.CreateConverterDictionary();
                }
                else
                {
                    converterDictionary = new Dictionary <string, object>();
                }

                state.Current.TempDictionaryValues = converterDictionary;

                // Clear the value if present to ensure we don't confuse TempDictionaryValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy && jsonPropertyInfo.CanBeNull)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject == null)
            {
                ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(jsonPropertyInfo.DeclaredPropertyType);
            }

            return(runtimeClassInfo.CreateObject());
        }
コード例 #6
0
        public static object CreateEnumerableValue(ref ReadStack state)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList         converterList;
                JsonClassInfo elementClassInfo = jsonPropertyInfo.ElementClassInfo;
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = elementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                // Clear the value if present to ensure we don't confuse TempEnumerableValues with the collection.
                if (!jsonPropertyInfo.IsPropertyPolicy && jsonPropertyInfo.CanBeNull)
                {
                    jsonPropertyInfo.SetValueAsObject(state.Current.ReturnValue, null);
                }

                return(null);
            }

            JsonClassInfo runtimeClassInfo = jsonPropertyInfo.RuntimeClassInfo;

            if (runtimeClassInfo.CreateObject == null)
            {
                ThrowHelper.ThrowNotSupportedException_DeserializeCreateObjectDelegateIsNull(jsonPropertyInfo.DeclaredPropertyType);
            }

            return(runtimeClassInfo.CreateObject());
        }
コード例 #7
0
ファイル: ReadStackFrame.cs プロジェクト: swellhh/corefx
        public static object CreateEnumerableValue(ref Utf8JsonReader reader, ref ReadStack state, JsonSerializerOptions options)
        {
            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            // If the property has an EnumerableConverter, then we use tempEnumerableValues.
            if (jsonPropertyInfo.EnumerableConverter != null)
            {
                IList converterList;
                if (jsonPropertyInfo.ElementClassInfo.ClassType == ClassType.Value)
                {
                    converterList = jsonPropertyInfo.ElementClassInfo.PolicyProperty.CreateConverterList();
                }
                else
                {
                    converterList = new List <object>();
                }

                state.Current.TempEnumerableValues = converterList;

                return(null);
            }

            Type propertyType = state.Current.JsonPropertyInfo.RuntimePropertyType;

            if (typeof(IList).IsAssignableFrom(propertyType))
            {
                // If IList, add the members as we create them.
                JsonClassInfo collectionClassInfo = state.Current.JsonPropertyInfo.RuntimeClassInfo;
                IList         collection          = (IList)collectionClassInfo.CreateObject();
                return(collection);
            }
            else
            {
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(propertyType, reader, state.JsonPath);
                return(null);
            }
        }
コード例 #8
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);
            }
        }
コード例 #9
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)
            {
                state.Push();
                state.Current.JsonClassInfo = jsonPropertyInfo.ElementClassInfo;
                state.Current.InitializeJsonPropertyInfo();
                state.Current.PropertyInitialized = true;

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

                JsonClassInfo classInfo = state.Current.JsonClassInfo;

                if (state.Current.IsProcessingIDictionaryConstructibleOrKeyValuePair)
                {
                    state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateObject();
                }
                else
                {
                    if (classInfo.CreateObject == null)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type, reader, state.JsonPath);
                        return;
                    }
                    state.Current.ReturnValue = classInfo.CreateObject();
                }
                return;
            }

            state.Current.PropertyInitialized = true;

            if (state.Current.IsProcessingIDictionaryConstructibleOrKeyValuePair)
            {
                JsonClassInfo dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.RuntimePropertyType);
                state.Current.TempDictionaryValues = (IDictionary)dictionaryClassInfo.CreateObject();
            }
            // Else if current property is already set (from a constructor, for example), leave as-is.
            else if (jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue) == null)
            {
                // Create the dictionary.
                JsonClassInfo dictionaryClassInfo = jsonPropertyInfo.RuntimeClassInfo;
                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);
                    }
                }
            }
        }
コード例 #10
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.CreateRootObject(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();
                state.Current.CollectionPropertyInitialized = true;

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

                JsonClassInfo classInfo = state.Current.JsonClassInfo;

                if (state.Current.IsProcessingIDictionaryConstructible())
                {
                    state.Current.TempDictionaryValues = (IDictionary)classInfo.CreateConcreteDictionary();
                }
                else
                {
                    if (classInfo.CreateObject == null)
                    {
                        ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type);
                        return;
                    }
                    state.Current.ReturnValue = classInfo.CreateObject();
                }

                return;
            }

            state.Current.CollectionPropertyInitialized = true;

            if (state.Current.IsProcessingIDictionaryConstructible())
            {
                JsonClassInfo dictionaryClassInfo;
                if (jsonPropertyInfo.DeclaredPropertyType == jsonPropertyInfo.ImplementedPropertyType)
                {
                    dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.RuntimePropertyType);
                }
                else
                {
                    dictionaryClassInfo = options.GetOrAddClass(jsonPropertyInfo.DeclaredPropertyType);
                }

                state.Current.TempDictionaryValues = (IDictionary)dictionaryClassInfo.CreateConcreteDictionary();
            }
            else
            {
                // Create the dictionary.
                JsonClassInfo dictionaryClassInfo = jsonPropertyInfo.RuntimeClassInfo;
                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);
                    }
                }
            }
        }
コード例 #11
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;

                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;
                }
            }
        }
コード例 #12
0
        private static void HandleStartObject(JsonSerializerOptions options, ref ReadStack state)
        {
            Debug.Assert(!state.Current.IsProcessingDictionaryOrIDictionaryConstructible());

            // 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.IDictionaryConstructible))
            {
                state.Current.TempDictionaryValues          = (IDictionary)classInfo.CreateConcreteDictionary();
                state.Current.CollectionPropertyInitialized = true;
            }
            else if (state.Current.IsProcessingObject(ClassType.Dictionary))
            {
                if (classInfo.CreateObject == null)
                {
                    throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection(classInfo.Type, parentType: null, memberInfo: null);
                }

                state.Current.ReturnValue = classInfo.CreateObject();
                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();

                if (state.Current.IsProcessingDictionary())
                {
                    state.Current.CollectionPropertyInitialized = true;
                }
            }
            else
            {
                // Only dictionaries or objects are valid given the `StartObject` token.
                ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(classInfo.Type);
            }
        }
コード例 #13
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;
                }
            }
        }