public override void WriteEnumerable(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(ShouldSerialize); if (ValueConverter != null) { Debug.Assert(current.Enumerator != null); TProperty?value; if (current.Enumerator is IEnumerator <TProperty?> enumerator) { // Avoid boxing for strongly-typed enumerators such as returned from IList<T>. value = enumerator.Current; } else { value = (TProperty?)current.Enumerator.Current; } if (value == null) { writer.WriteNullValue(); } else { ValueConverter.Write(value.GetValueOrDefault(), writer); } } }
internal static void WriteDictionary <TProperty>( JsonConverter <TProperty> converter, JsonSerializerOptions options, ref WriteStackFrame current, Utf8JsonWriter writer) { if (converter == null) { return; } Debug.Assert(current.CollectionEnumerator != null); string key; TProperty value; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty> > enumerator) { // Avoid boxing for strongly-typed enumerators such as returned from IDictionary<string, TRuntimeProperty> value = enumerator.Current.Value; key = enumerator.Current.Key; } else if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, object> > polymorphicEnumerator) { value = (TProperty)polymorphicEnumerator.Current.Value; key = polymorphicEnumerator.Current.Key; } else if (current.IsIDictionaryConstructible || current.IsIDictionaryConstructibleProperty) { value = (TProperty)((DictionaryEntry)current.CollectionEnumerator.Current).Value; key = (string)((DictionaryEntry)current.CollectionEnumerator.Current).Key; } else { // Todo: support non-generic Dictionary here (IDictionaryEnumerator) throw new NotSupportedException(); } if (value == null) { writer.WriteNull(key); } else { if (options.DictionaryKeyPolicy != null && current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // We do not convert extension data. { key = options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType()); } } JsonEncodedText escapedKey = JsonEncodedText.Encode(key, options.Encoder); writer.WritePropertyName(escapedKey); converter.Write(writer, value, options); } }
internal static void WriteDictionary <TProperty>( JsonConverter <TProperty> converter, JsonSerializerOptions options, ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(converter != null && current.CollectionEnumerator != null); string key; TProperty value; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, object> > polymorphicEnumerator) { key = polymorphicEnumerator.Current.Key; value = (TProperty)polymorphicEnumerator.Current.Value; } else if (current.CollectionEnumerator is IDictionaryEnumerator iDictionaryEnumerator && iDictionaryEnumerator.Key is string keyAsString) { key = keyAsString; value = (TProperty)iDictionaryEnumerator.Value !; }
protected override void OnWrite(ref WriteStackFrame current, Utf8JsonWriter writer) { TConverter value; if (IsPropertyPolicy) { value = (TConverter)current.CurrentValue; } else { value = (TConverter)Get(current.CurrentValue); } if (value == null) { Debug.Assert(EscapedName.HasValue); if (!IgnoreNullValues) { writer.WriteNull(EscapedName.Value); } } else if (Converter != null) { if (EscapedName.HasValue) { writer.WritePropertyName(EscapedName.Value); } Converter.Write(writer, value, Options); } }
public void GetDictionaryKeyAndValue(ref WriteStackFrame writeStackFrame, out string key, out object value) { Debug.Assert(ClassType == ClassType.Dictionary); if (writeStackFrame.CollectionEnumerator is IDictionaryEnumerator iDictionaryEnumerator) { if (iDictionaryEnumerator.Key is string keyAsString) { // Since IDictionaryEnumerator is not based on generics we can obtain the value directly. key = keyAsString; value = iDictionaryEnumerator.Value; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( writeStackFrame.JsonPropertyInfo.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } } else { // Forward to the generic dictionary. DictionaryValuePropertyPolicy.GetDictionaryKeyAndValueFromGenericDictionary(ref writeStackFrame, out key, out value); } }
protected override void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonWriter writer) { if (Converter != null) { Debug.Assert(current.CollectionEnumerator != null); TConverter value; if (current.CollectionEnumerator is IEnumerator <TConverter> enumerator) { // Avoid boxing for strongly-typed enumerators such as returned from IList<T>. value = enumerator.Current; } else { value = (TConverter)current.CollectionEnumerator.Current; } if (value == null) { writer.WriteNullValue(); } else { Converter.Write(writer, value, Options); } } }
internal static void WriteDictionary <TProperty>( JsonConverter <TProperty> converter, JsonSerializerOptions options, ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(converter != null && current.CollectionEnumerator != null); string key; TProperty value; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, object> > polymorphicEnumerator) { key = polymorphicEnumerator.Current.Key; value = (TProperty)polymorphicEnumerator.Current.Value; } else { if (((DictionaryEntry)current.CollectionEnumerator.Current).Key is string keyAsString) { key = keyAsString; value = (TProperty)((DictionaryEntry)current.CollectionEnumerator.Current).Value; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( current.JsonPropertyInfo.DeclaredPropertyType, current.JsonPropertyInfo.ParentClassType, current.JsonPropertyInfo.PropertyInfo); } } if (value == null) { writer.WriteNull(key); } else { if (options.DictionaryKeyPolicy != null && current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing) // We do not convert extension data. { key = options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(options.DictionaryKeyPolicy.GetType()); } } writer.WritePropertyName(key); converter.Write(writer, value, options); } }
public void Pop(bool success) { Debug.Assert(_count > 0); if (!success) { // Check if we need to initialize the continuation. if (_continuationCount == 0) { if (_count == 1) { // No need for a continuation since there is only one stack frame. _continuationCount = 1; _count = 1; } else { AddCurrent(); _count--; _continuationCount = _count; _count--; Current = _previous[_count - 1]; } return; } if (_continuationCount == 1) { // No need for a pop since there is only one stack frame. Debug.Assert(_count == 1); return; } // Update the list entry to the current value. _previous[_count - 1] = Current; Debug.Assert(_count > 0); } else { Debug.Assert(_continuationCount == 0); if (Current.AsyncEnumerator is not null) { // we have completed serialization of an AsyncEnumerator, // pop from the stack and schedule for async disposal. PendingAsyncDisposables ??= new List <IAsyncDisposable>(); PendingAsyncDisposables.Add(Current.AsyncEnumerator); } } if (_count > 1) { Current = _previous[--_count - 1]; } }
// There are three conditions to consider for an object (primitive value, enumerable or object) being processed here: // 1) The object type was specified as the root-level return type to a Parse\Read method. // 2) The object is property on a parent object. // 3) The object is an element in an enumerable. private static bool Write( Utf8JsonWriter writer, int flushThreshold, JsonSerializerOptions options, ref WriteStack state) { bool finishedSerializing; do { WriteStackFrame current = state.Current; switch (current.JsonClassInfo.ClassType) { case ClassType.Enumerable: finishedSerializing = HandleEnumerable(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; case ClassType.Value: Debug.Assert(current.JsonPropertyInfo.ClassType == ClassType.Value); current.JsonPropertyInfo.Write(ref current, writer); finishedSerializing = true; break; case ClassType.Object: case ClassType.KeyValuePair: finishedSerializing = WriteObject(options, writer, ref state); break; case ClassType.Dictionary: case ClassType.IDictionaryConstructible: finishedSerializing = HandleDictionary(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; default: Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Unknown); // Treat typeof(object) as an empty object. finishedSerializing = WriteObject(options, writer, ref state); break; } if (finishedSerializing && writer.CurrentDepth == 0) { break; } // If serialization is not yet end and we surpass beyond flush threshold return false and flush stream. if (flushThreshold >= 0 && writer.BytesPending > flushThreshold) { return(false); } } while (true); return(true); }
protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(Converter != null && current.CollectionEnumerator != null); string key = null; TProperty?value = null; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty?> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else { if (((DictionaryEntry)current.CollectionEnumerator.Current).Key is string keyAsString) { key = keyAsString; value = (TProperty?)((DictionaryEntry)current.CollectionEnumerator.Current).Value; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( current.JsonPropertyInfo.DeclaredPropertyType, current.JsonPropertyInfo.ParentClassType, current.JsonPropertyInfo.PropertyInfo); } } Debug.Assert(key != null); if (Options.DictionaryKeyPolicy != null) { // We should not be in the Nullable-value implementation branch for extension data. // (TValue should be typeof(object) or typeof(JsonElement)). Debug.Assert(current.ExtensionDataStatus != ExtensionDataWriteStatus.Writing); key = Options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(Options.DictionaryKeyPolicy.GetType()); } } if (value == null) { writer.WriteNull(key); } else { writer.WritePropertyName(key); Converter.Write(writer, value.GetValueOrDefault(), Options); } }
protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(Converter != null && current.CollectionEnumerator != null); string key = null; TProperty?value = null; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty?> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else { if (((DictionaryEntry)current.CollectionEnumerator.Current).Key is string keyAsString) { key = keyAsString; value = (TProperty?)((DictionaryEntry)current.CollectionEnumerator.Current).Value; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( current.JsonPropertyInfo.DeclaredPropertyType, current.JsonPropertyInfo.ParentClassType, current.JsonPropertyInfo.PropertyInfo); } } Debug.Assert(key != null); if (value == null) { writer.WriteNull(key); } else { if (Options.DictionaryKeyPolicy != null) { key = Options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(Options.DictionaryKeyPolicy.GetType()); } } writer.WritePropertyName(key); Converter.Write(writer, value.GetValueOrDefault(), Options); } }
public void Pop(bool success) { Debug.Assert(_count > 0); if (!success) { // Check if we need to initialize the continuation. if (_continuationCount == 0) { if (_count == 1) { // No need for a continuation since there is only one stack frame. _continuationCount = 1; _count = 1; } else { AddCurrent(); _count--; _continuationCount = _count; _count--; Current = _previous[_count - 1]; } return; } if (_continuationCount == 1) { // No need for a pop since there is only one stack frame. Debug.Assert(_count == 1); return; } // Update the list entry to the current value. _previous[_count - 1] = Current; Debug.Assert(_count > 0); } else { Debug.Assert(_continuationCount == 0); } if (_count > 1) { Current = _previous[--_count - 1]; } }
public void Pop(bool success) { Debug.Assert(_count > 0); if (!success) { // Check if we need to initialize the continuation. if (_continuationCount == 0) { if (_count == 1) { // No need to copy any frames here. _continuationCount = 1; _count = 0; return; } // Need to push the Current frame to the stack, // ensure that we have sufficient capacity. EnsurePushCapacity(); _continuationCount = _count--; } else if (--_count == 0) { // reached the root, no need to copy frames. return; } _stack[_count] = Current; Current = _stack[_count - 1]; } else { Debug.Assert(_continuationCount == 0); if (Current.AsyncEnumerator is not null) { // we have completed serialization of an AsyncEnumerator, // pop from the stack and schedule for async disposal. PendingAsyncDisposables ??= new List <IAsyncDisposable>(); PendingAsyncDisposables.Add(Current.AsyncEnumerator); } if (--_count > 0) { Current = _stack[_count - 1]; } } }
public void Push() { if (_continuationCount == 0) { Debug.Assert(Current.PolymorphicSerializationState != PolymorphicSerializationState.PolymorphicReEntrySuspended); if (_count == 0 && Current.PolymorphicSerializationState == PolymorphicSerializationState.None) { // Perf enhancement: do not create a new stackframe on the first push operation // unless the converter has primed the current frame for polymorphic dispatch. _count = 1; _indexOffset = 1; // currentIndex := _count - 1; } else { JsonTypeInfo jsonTypeInfo = Current.GetNestedJsonTypeInfo(); JsonNumberHandling?numberHandling = Current.NumberHandling; EnsurePushCapacity(); _stack[_count - _indexOffset] = Current; Current = default; _count++; Current.JsonTypeInfo = jsonTypeInfo; Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; // Allow number handling on property to win over handling on type. Current.NumberHandling = numberHandling ?? Current.JsonPropertyInfo.EffectiveNumberHandling; } } else { // We are re-entering a continuation, adjust indices accordingly if (_count++ > 0 || _indexOffset == 0) { Current = _stack[_count - _indexOffset]; } // check if we are done if (_continuationCount == _count) { _continuationCount = 0; } } #if DEBUG // Ensure the method is always exercised in debug builds. _ = PropertyPath(); #endif }
public override void GetDictionaryKeyAndValueFromGenericDictionary(ref WriteStackFrame writeStackFrame, out string key, out object?value) { if (writeStackFrame.CollectionEnumerator is IEnumerator <KeyValuePair <string, TDeclaredProperty> > genericEnumerator) { key = genericEnumerator.Current.Key; value = genericEnumerator.Current.Value; } else { throw ThrowHelper.GetNotSupportedException_SerializationNotSupportedCollection( writeStackFrame.JsonPropertyInfo !.DeclaredPropertyType, writeStackFrame.JsonPropertyInfo.ParentClassType, writeStackFrame.JsonPropertyInfo.PropertyInfo); } }
internal static void WriteDictionary <TProperty>( JsonValueConverter <TProperty> converter, JsonSerializerOptions options, ref WriteStackFrame current, Utf8JsonWriter writer) { if (converter == null) { return; } Debug.Assert(current.Enumerator != null); string key; TProperty value; if (current.Enumerator is IEnumerator <KeyValuePair <string, TProperty> > enumerator) { // Avoid boxing for strongly-typed enumerators such as returned from IDictionary<string, TRuntimeProperty> value = enumerator.Current.Value; key = enumerator.Current.Key; } else if (current.Enumerator is IEnumerator <KeyValuePair <string, object> > polymorphicEnumerator) { value = (TProperty)polymorphicEnumerator.Current.Value; key = polymorphicEnumerator.Current.Key; } else if (current.IsImmutableDictionary || current.IsImmutableDictionaryProperty) { value = (TProperty)((DictionaryEntry)current.Enumerator.Current).Value; key = (string)((DictionaryEntry)current.Enumerator.Current).Key; } else { // Todo: support non-generic Dictionary here (IDictionaryEnumerator) throw new NotSupportedException(); } if (value == null) { writer.WriteNull(key); } else { JsonEncodedText escapedKey = JsonEncodedText.Encode(key); converter.Write(escapedKey, value, writer); } }
private static void WriteExtensionData(Utf8JsonWriter writer, ref WriteStackFrame frame) { DictionaryEntry entry = ((IDictionaryEnumerator)frame.Enumerator).Entry; if (entry.Value is JsonElement element) { Debug.Assert(entry.Key is string); string propertyName = (string)entry.Key; element.WriteProperty(propertyName, writer); } else { ThrowHelper.ThrowInvalidOperationException_SerializationDataExtensionPropertyInvalid(frame.JsonClassInfo, entry.Value.GetType()); } }
public void Push() { if (_continuationCount == 0) { if (_count == 0) { // Performance optimization: reuse the first stackframe on the first push operation. // NB need to be careful when making writes to Current _before_ the first `Push` // operation is performed. _count = 1; } else { JsonTypeInfo jsonTypeInfo = Current.GetNestedJsonTypeInfo(); JsonNumberHandling?numberHandling = Current.NumberHandling; EnsurePushCapacity(); _stack[_count - 1] = Current; Current = default; _count++; Current.JsonTypeInfo = jsonTypeInfo; Current.JsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; // Allow number handling on property to win over handling on type. Current.NumberHandling = numberHandling ?? Current.JsonPropertyInfo.NumberHandling; } } else { // We are re-entering a continuation, adjust indices accordingly if (_count++ > 0) { Current = _stack[_count - 1]; } // check if we are done if (_continuationCount == _count) { _continuationCount = 0; } } #if DEBUG // Ensure the method is always exercised in debug builds. _ = PropertyPath(); #endif }
public void Push() { if (_continuationCount == 0) { if (_count == 0) { // The first stack frame is held in Current. _count = 1; } else { JsonTypeInfo jsonTypeInfo = Current.GetPolymorphicJsonPropertyInfo().RuntimeTypeInfo; JsonNumberHandling?numberHandling = Current.NumberHandling; AddCurrent(); Current.Reset(); Current.JsonTypeInfo = jsonTypeInfo; Current.DeclaredJsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; // Allow number handling on property to win over handling on type. Current.NumberHandling = numberHandling ?? Current.DeclaredJsonPropertyInfo.NumberHandling; } } else if (_continuationCount == 1) { // No need for a push since there is only one stack frame. Debug.Assert(_count == 1); _continuationCount = 0; } else { // A continuation, adjust the index. Current = _previous[_count - 1]; // Check if we are done. if (_count == _continuationCount) { _continuationCount = 0; } else { _count++; } } }
public void Push() { if (_continuationCount == 0) { if (_count == 0) { // The first stack frame is held in Current. _count = 1; } else { JsonTypeInfo jsonTypeInfo = Current.GetPolymorphicJsonPropertyInfo().RuntimeTypeInfo; JsonNumberHandling?numberHandling = Current.NumberHandling; EnsurePushCapacity(); _stack[_count - 1] = Current; Current = default; _count++; Current.JsonTypeInfo = jsonTypeInfo; Current.DeclaredJsonPropertyInfo = jsonTypeInfo.PropertyInfoForTypeInfo; // Allow number handling on property to win over handling on type. Current.NumberHandling = numberHandling ?? Current.DeclaredJsonPropertyInfo.NumberHandling; } } else { // We are re-entering a continuation, adjust indices accordingly if (_count++ > 0) { Current = _stack[_count - 1]; } // check if we are done if (_continuationCount == _count) { _continuationCount = 0; } } #if DEBUG // Ensure the method is always exercised in debug builds. _ = PropertyPath(); #endif }
public override void Write(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(ShouldSerialize); if (current.Enumerator != null) { // Forward the setter to the value-based JsonPropertyInfo. JsonPropertyInfo propertyInfo = ElementClassInfo.GetPolicyProperty(); propertyInfo.WriteEnumerable(ref current, writer); } else { TProperty?value; if (IsPropertyPolicy) { value = (TProperty?)current.CurrentValue; } else { value = 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.GetValueOrDefault(), writer); } else { ValueConverter.Write(value.GetValueOrDefault(), writer); } } } }
protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(Converter != null && current.CollectionEnumerator != null); string? key = null; TProperty?value = null; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty?> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else { if (((DictionaryEntry)current.CollectionEnumerator.Current !).Key is string keyAsString) { key = keyAsString; value = (TProperty?)((DictionaryEntry)current.CollectionEnumerator.Current).Value; }
public void Push() { if (_continuationCount == 0) { if (_count == 0) { // The first stack frame is held in Current. _count = 1; } else { JsonClassInfo jsonClassInfo = Current.GetPolymorphicJsonPropertyInfo().RuntimeClassInfo; AddCurrent(); Current.Reset(); Current.JsonClassInfo = jsonClassInfo; Current.DeclaredJsonPropertyInfo = jsonClassInfo.PropertyInfoForClassInfo; } } else if (_continuationCount == 1) { // No need for a push since there is only one stack frame. Debug.Assert(_count == 1); _continuationCount = 0; } else { // A continuation, adjust the index. Current = _previous[_count - 1]; // Check if we are done. if (_count == _continuationCount) { _continuationCount = 0; } else { _count++; } } }
public void Pop(bool success) { Debug.Assert(_count > 0); if (!success) { // Check if we need to initialize the continuation. if (_continuationCount == 0) { if (_count == 1 && _indexOffset > 0) { // No need to copy any frames here. _continuationCount = 1; _count = 0; return; } // Need to push the Current frame to the stack, // ensure that we have sufficient capacity. EnsurePushCapacity(); _continuationCount = _count--; } else if (--_count == 0 && _indexOffset > 0) { // reached the root, no need to copy frames. return; } int currentIndex = _count - _indexOffset; _stack[currentIndex + 1] = Current; Current = _stack[currentIndex]; } else { Debug.Assert(_continuationCount == 0); if (--_count > 0 || _indexOffset == 0) { Current = _stack[_count - _indexOffset]; } } }
protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { Debug.Assert(Converter != null && current.CollectionEnumerator != null); string key = null; TProperty?value = null; if (current.CollectionEnumerator is IEnumerator <KeyValuePair <string, TProperty?> > enumerator) { key = enumerator.Current.Key; value = enumerator.Current.Value; } else if (current.IsIDictionaryConstructible || current.IsIDictionaryConstructibleProperty) { key = (string)((DictionaryEntry)current.CollectionEnumerator.Current).Key; value = (TProperty?)((DictionaryEntry)current.CollectionEnumerator.Current).Value; } Debug.Assert(key != null); if (value == null) { writer.WriteNull(key); } else { if (Options.DictionaryKeyPolicy != null) { key = Options.DictionaryKeyPolicy.ConvertName(key); if (key == null) { ThrowHelper.ThrowInvalidOperationException_SerializerDictionaryKeyNull(Options.DictionaryKeyPolicy.GetType()); } } writer.WritePropertyName(key); Converter.Write(writer, value.GetValueOrDefault(), Options); } }
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); } } }
protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { JsonSerializer.WriteDictionary(Converter, Options, ref current, writer); }
protected abstract void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonWriter writer);
protected virtual void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer) { }
// There are three conditions to consider for an object (primitive value, enumerable or object) being processed here: // 1) The object type was specified as the root-level return type to a Parse\Read method. // 2) The object is property on a parent object. // 3) The object is an element in an enumerable. private static bool Write( Utf8JsonWriter writer, int flushThreshold, JsonSerializerOptions options, ref WriteStack state) { bool finishedSerializing; int currentDepth = writer.CurrentDepth; try { do { WriteStackFrame current = state.Current; switch (current.JsonClassInfo.ClassType) { case ClassType.Enumerable: finishedSerializing = HandleEnumerable(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; case ClassType.Value: Debug.Assert(current.JsonPropertyInfo.ClassType == ClassType.Value); current.JsonPropertyInfo.Write(ref state, writer); finishedSerializing = true; break; case ClassType.Object: finishedSerializing = WriteObject(options, writer, ref state); break; case ClassType.Dictionary: case ClassType.IDictionaryConstructible: finishedSerializing = HandleDictionary(current.JsonClassInfo.ElementClassInfo, options, writer, ref state); break; default: Debug.Assert(state.Current.JsonClassInfo.ClassType == ClassType.Unknown); // Treat typeof(object) as an empty object. finishedSerializing = WriteObject(options, writer, ref state); break; } if (finishedSerializing) { if (writer.CurrentDepth == 0 || writer.CurrentDepth == currentDepth) { break; } } else if (writer.CurrentDepth >= options.EffectiveMaxDepth) { ThrowHelper.ThrowJsonException_DepthTooLarge(writer.CurrentDepth, state, options); } // If serialization is not yet end and we surpass beyond flush threshold return false and flush stream. if (flushThreshold >= 0 && writer.BytesPending > flushThreshold) { return(false); } } while (true); } catch (InvalidOperationException ex) when(ex.Source == ThrowHelper.ExceptionSourceValueToRethrowAsJsonException) { ThrowHelper.ReThrowWithPath(state, ex); } catch (JsonException ex) { ThrowHelper.AddExceptionInformation(state, ex); throw; } return(true); }