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