Beispiel #1
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #6
0
        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);
        }
Beispiel #9
0
        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);
        }