Esempio n. 1
0
        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);
            }
        }
Esempio n. 3
0
        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 !;
            }
Esempio n. 4
0
        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);
            }
        }
Esempio n. 5
0
        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);
            }
        }
Esempio n. 6
0
        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);
                }
            }
        }
Esempio n. 7
0
        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);
            }
        }
Esempio n. 8
0
        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];
            }
        }
Esempio n. 9
0
        // 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);
        }
Esempio n. 10
0
        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);
            }
        }
Esempio n. 12
0
        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];
            }
        }
Esempio n. 13
0
        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];
                }
            }
        }
Esempio n. 14
0
        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);
     }
 }
Esempio n. 16
0
        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);
            }
        }
Esempio n. 17
0
        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());
            }
        }
Esempio n. 18
0
        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
        }
Esempio n. 19
0
        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++;
                }
            }
        }
Esempio n. 20
0
        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
        }
Esempio n. 21
0
        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);
                    }
                }
            }
        }
Esempio n. 22
0
        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;
                }
Esempio n. 23
0
        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++;
                }
            }
        }
Esempio n. 24
0
        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];
                }
            }
        }
Esempio n. 25
0
        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);
            }
        }
Esempio n. 26
0
        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);
                }
            }
        }
Esempio n. 27
0
 protected override void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer)
 {
     JsonSerializer.WriteDictionary(Converter, Options, ref current, writer);
 }
Esempio n. 28
0
 protected abstract void OnWriteEnumerable(ref WriteStackFrame current, Utf8JsonWriter writer);
Esempio n. 29
0
 protected virtual void OnWriteDictionary(ref WriteStackFrame current, Utf8JsonWriter writer)
 {
 }
Esempio n. 30
0
        // 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);
        }