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