private static bool WriteObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { // Write the start. if (!state.Current.StartObjectWritten) { state.Current.WriteObjectOrArrayStart(ClassType.Object, writer); } // Determine if we are done enumerating properties. // If the ClassType is unknown, there will be a policy property applied. There is probably // a better way to identify policy properties- maybe not put them in the normal property bag? JsonClassInfo classInfo = state.Current.JsonClassInfo; if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyIndex != classInfo.PropertyCount) { HandleObject(options, writer, ref state); return(false); } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
private static bool WriteEndObject(ref WriteStack state) { if (state.Current.PopStackOnEndObject) { state.Pop(); } return(true); }
private static bool WriteObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { // Write the start. if (!state.Current.StartObjectWritten) { state.Current.WriteObjectOrArrayStart(ClassType.Object, writer); state.Current.PropertyEnumerator = state.Current.JsonClassInfo.PropertyCache.GetEnumerator(); state.Current.PropertyEnumeratorActive = true; state.Current.NextProperty(); } else if (state.Current.MoveToNextProperty) { state.Current.NextProperty(); } // Determine if we are done enumerating properties. // If the ClassType is unknown, there will be a policy property applied JsonClassInfo classInfo = state.Current.JsonClassInfo; if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyEnumeratorActive) { var kvp = (KeyValuePair <string, JsonPropertyInfo>)state.Current.PropertyEnumerator.Current; JsonPropertyInfo jsonPropertyInfo = kvp.Value; HandleObject(jsonPropertyInfo, options, writer, ref state); return(false); } if (state.Current.ExtensionDataStatus == Serialization.ExtensionDataWriteStatus.Writing) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.DataExtensionProperty; if (jsonPropertyInfo != null) { HandleObject(jsonPropertyInfo, options, writer, ref state); return(false); } } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
private static bool WriteEndDictionary(ref WriteStack state) { if (state.Current.PopStackOnEndCollection) { state.Pop(); } else { state.Current.EndDictionary(); } return(true); }
private static bool WriteObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { // Write the start. if (!state.Current.StartObjectWritten) { state.Current.WriteObjectOrArrayStart(ClassType.Object, writer); state.Current.PropertyEnumerator = state.Current.JsonClassInfo.PropertyCache.GetEnumerator(); state.Current.NextProperty(); } else if (state.Current.MoveToNextProperty) { state.Current.NextProperty(); } // Determine if we are done enumerating properties. // If the ClassType is unknown, there will be a policy property applied JsonClassInfo classInfo = state.Current.JsonClassInfo; if (classInfo.ClassType != ClassType.Unknown && state.Current.PropertyEnumeratorActive) { HandleObject(options, writer, ref state); return(false); } writer.WriteEndObject(); if (state.Current.PopStackOnEndObject) { state.Pop(); } else { state.Current.EndObject(); } return(true); }
private static bool HandleDictionary( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo !; if (state.Current.CollectionEnumerator == null) { IEnumerable?enumerable = (IEnumerable?)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { if ((state.Current.JsonClassInfo !.ClassType != ClassType.Object || // Write null dictionary values !jsonPropertyInfo.IgnoreNullValues) && // Ignore ClassType.Object properties if IgnoreNullValues is true state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // Ignore null extension property (which is a dictionary) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options, writeNull: true); } if (state.Current.PopStackOnEndCollection) { state.Pop(); } return(true); } if (state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) { if (options.ReferenceHandling.ShouldWritePreservedReferences()) { if (WriteReference(ref state, writer, options, ClassType.Dictionary, enumerable)) { return(WriteEndDictionary(ref state)); } } else { state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options); } } // Let the dictionary return the default IEnumerator from its IEnumerable.GetEnumerator(). // For IDictionary-derived classes this is normally be IDictionaryEnumerator. // For IDictionary<TKey, TVale>-derived classes this is normally IDictionaryEnumerator as well // but may be IEnumerable<KeyValuePair<TKey, TValue>> if the dictionary only supports generics. state.Current.CollectionEnumerator = enumerable.GetEnumerator(); } if (state.Current.CollectionEnumerator.MoveNext()) { // A dictionary should not have a null KeyValuePair. Debug.Assert(state.Current.CollectionEnumerator.Current != null); bool obtainedValues = false; string?key = default; object?value = default; // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { jsonPropertyInfo.GetDictionaryKeyAndValue(ref state.Current, out key, out value); GetRuntimeClassInfo(value, ref elementClassInfo, options); obtainedValues = true; } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.PolicyProperty !.WriteDictionary(ref state, writer); } else { if (!obtainedValues) { jsonPropertyInfo.GetDictionaryKeyAndValue(ref state.Current, out key, out value); } if (options.DictionaryKeyPolicy != null && state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) { Debug.Assert(key != null); key = options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType()); } } // An object or another enumerator requires a new stack frame. state.Push(elementClassInfo, value); state.Current.KeyName = key; } return(false); } // We are done enumerating. if (state.Current.ExtensionDataStatus == ExtensionDataWriteStatus.Writing) { state.Current.ExtensionDataStatus = ExtensionDataWriteStatus.Finished; } else { writer.WriteEndObject(); } return(WriteEndDictionary(ref state)); }
private static bool HandleEnumerable( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable); if (state.Current.CollectionEnumerator == null) { IEnumerable enumerable = (IEnumerable)state.Current.JsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { // If applicable, we only want to ignore object properties. if (state.Current.JsonClassInfo.ClassType != ClassType.Object || !state.Current.JsonPropertyInfo.IgnoreNullValues) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Enumerable, writer, writeNull: true); } if (state.Current.PopStackOnEndCollection) { state.Pop(); } return(true); } state.Current.CollectionEnumerator = enumerable.GetEnumerator(); state.Current.WriteObjectOrArrayStart(ClassType.Enumerable, writer); } if (state.Current.CollectionEnumerator.MoveNext()) { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = state.Current.CollectionEnumerator.Current; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.PolicyProperty.WriteEnumerable(ref state, writer); } else if (state.Current.CollectionEnumerator.Current == null) { // Write a null object or enumerable. writer.WriteNullValue(); } else { // An object or another enumerator requires a new stack frame. object nextValue = state.Current.CollectionEnumerator.Current; state.Push(elementClassInfo, nextValue); } return(false); } // We are done enumerating. writer.WriteEndArray(); if (state.Current.PopStackOnEndCollection) { state.Pop(); } else { state.Current.EndArray(); } return(true); }
private static bool HandleDictionary( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (state.Current.CollectionEnumerator == null) { IEnumerable enumerable; enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { if ((state.Current.JsonClassInfo.ClassType != ClassType.Object || // Write null dictionary values !state.Current.JsonPropertyInfo.IgnoreNullValues) && // Ignore ClassType.Object properties if IgnoreNullValues is true state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // Ignore null extension property (which is a dictionary) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options, writeNull: true); } if (state.Current.PopStackOnEndCollection) { state.Pop(); } return(true); } if (enumerable is IDictionary dictionary) { state.Current.CollectionEnumerator = dictionary.GetEnumerator(); } else { state.Current.CollectionEnumerator = enumerable.GetEnumerator(); } if (state.Current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) { state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, options); } } if (state.Current.CollectionEnumerator.MoveNext()) { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = ((IDictionaryEnumerator)state.Current.CollectionEnumerator).Entry.Value; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.PolicyProperty.WriteDictionary(ref state, writer); } else if (state.Current.CollectionEnumerator.Current == null) { writer.WriteNull(jsonPropertyInfo.Name); } else { // An object or another enumerator requires a new stack frame. var enumerator = (IDictionaryEnumerator)state.Current.CollectionEnumerator; object value = enumerator.Value; state.Push(elementClassInfo, value); state.Current.KeyName = (string)enumerator.Key; } return(false); } // We are done enumerating. if (state.Current.ExtensionDataStatus == ExtensionDataWriteStatus.Writing) { state.Current.ExtensionDataStatus = ExtensionDataWriteStatus.Finished; } else { writer.WriteEndObject(); } if (state.Current.PopStackOnEndCollection) { state.Pop(); } else { state.Current.EndDictionary(); } return(true); }
private static bool HandleDictionary( JsonClassInfo elementClassInfo, JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo; if (state.Current.Enumerator == null) { IEnumerable enumerable; enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); if (enumerable == null) { // Write a null object or enumerable. state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer, writeNull: true); return(true); } state.Current.Enumerator = ((IDictionary)enumerable).GetEnumerator(); state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer); } if (state.Current.Enumerator.MoveNext()) { // Handle DataExtension. if (ReferenceEquals(jsonPropertyInfo, state.Current.JsonClassInfo.DataExtensionProperty)) { WriteExtensionData(writer, ref state.Current); } else { // Check for polymorphism. if (elementClassInfo.ClassType == ClassType.Unknown) { object currentValue = ((IDictionaryEnumerator)state.Current.Enumerator).Entry.Value; GetRuntimeClassInfo(currentValue, ref elementClassInfo, options); } if (elementClassInfo.ClassType == ClassType.Value) { elementClassInfo.GetPolicyProperty().WriteDictionary(ref state.Current, writer); } else if (state.Current.Enumerator.Current == null) { writer.WriteNull(jsonPropertyInfo.Name); } else { // An object or another enumerator requires a new stack frame. var enumerator = (IDictionaryEnumerator)state.Current.Enumerator; object value = enumerator.Value; state.Push(elementClassInfo, value); state.Current.KeyName = (string)enumerator.Key; } } return(false); } // We are done enumerating. writer.WriteEndObject(); if (state.Current.PopStackOnEnd) { state.Pop(); } else { state.Current.EndDictionary(); } return(true); }