public override void Write(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(current.Enumerator == null); Debug.Assert(ShouldSerialize); TRuntimeProperty value; if (IsPropertyPolicy) { value = (TRuntimeProperty)current.CurrentValue; } else { value = (TRuntimeProperty)Get(current.CurrentValue); } if (value == null) { Debug.Assert(EscapedName.HasValue); if (!IgnoreNullValues) { writer.WriteNull(EscapedName.Value); } } else if (ValueConverter != null) { if (EscapedName.HasValue) { ValueConverter.Write(EscapedName.Value, value, writer); } else { ValueConverter.Write(value, writer); } } }
private static bool HandleObject( JsonSerializerOptions options, Utf8JsonWriter writer, ref WriteStack state) { Debug.Assert( state.Current.JsonClassInfo.ClassType == ClassType.Object || state.Current.JsonClassInfo.ClassType == ClassType.Unknown); JsonPropertyInfo jsonPropertyInfo = state.Current.JsonClassInfo.GetProperty(state.Current.PropertyIndex); if (!jsonPropertyInfo.ShouldSerialize) { state.Current.MoveToNextProperty = true; return(true); } bool obtainedValue = false; object currentValue = null; // Check for polymorphism. if (jsonPropertyInfo.ClassType == ClassType.Unknown) { currentValue = jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); obtainedValue = true; GetRuntimePropertyInfo(currentValue, state.Current.JsonClassInfo, ref jsonPropertyInfo, options); } state.Current.JsonPropertyInfo = jsonPropertyInfo; if (jsonPropertyInfo.ClassType == ClassType.Value) { jsonPropertyInfo.Write(ref state, writer); state.Current.MoveToNextProperty = true; return(true); } // A property that returns an enumerator keeps the same stack frame. if (jsonPropertyInfo.ClassType == ClassType.Enumerable) { bool endOfEnumerable = HandleEnumerable(jsonPropertyInfo.ElementClassInfo, options, writer, ref state); if (endOfEnumerable) { state.Current.MoveToNextProperty = true; } return(endOfEnumerable); } // A property that returns a dictionary keeps the same stack frame. if (jsonPropertyInfo.ClassType == ClassType.Dictionary) { bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo, options, writer, ref state); if (endOfEnumerable) { state.Current.MoveToNextProperty = true; } return(endOfEnumerable); } // A property that returns an immutable dictionary keeps the same stack frame. if (jsonPropertyInfo.ClassType == ClassType.IDictionaryConstructible) { state.Current.IsIDictionaryConstructibleProperty = true; bool endOfEnumerable = HandleDictionary(jsonPropertyInfo.ElementClassInfo, options, writer, ref state); if (endOfEnumerable) { state.Current.MoveToNextProperty = true; } return(endOfEnumerable); } // A property that returns an object. if (!obtainedValue) { currentValue = jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue); } if (currentValue != null) { // A new stack frame is required. JsonPropertyInfo previousPropertyInfo = state.Current.JsonPropertyInfo; state.Current.MoveToNextProperty = true; JsonClassInfo nextClassInfo = jsonPropertyInfo.RuntimeClassInfo; state.Push(nextClassInfo, currentValue); // Set the PropertyInfo so we can obtain the property name in order to write it. state.Current.JsonPropertyInfo = previousPropertyInfo; } else { if (!jsonPropertyInfo.IgnoreNullValues) { writer.WriteNull(jsonPropertyInfo.EscapedName.Value); } state.Current.MoveToNextProperty = true; } 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); }