private static bool WriteObject(
            JsonSerializerOptions options,
            Utf8JsonWriter writer,
            ref WriteStack state)
        {
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            // Write the start.
            if (!state.Current.StartObjectWritten)
            {
                state.Current.WriteObjectOrArrayStart(ClassType.Object, writer);
            }

            // Determine if we are done enumerating properties.
            if (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 HandleEnumerable(
            JsonClassInfo elementClassInfo,
            JsonSerializerOptions options,
            ref Utf8JsonWriter writer,
            ref WriteStack state)
        {
            Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable);

            JsonPropertyInfo propertyInfo = state.Current.JsonPropertyInfo;

            if (state.Current.Enumerator == null)
            {
                if (propertyInfo._name == null)
                {
                    writer.WriteStartArray();
                }
                else
                {
                    writer.WriteStartArray(propertyInfo._name);
                }

                IEnumerable enumerable = (IEnumerable)propertyInfo.GetValueAsObject(state.Current.CurrentValue, options);

                if (enumerable != null)
                {
                    state.Current.Enumerator = enumerable.GetEnumerator();
                }
            }

            if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext())
            {
                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer);
                }
                else
                {
                    // An object or another enumerator requires a new stack frame
                    JsonClassInfo nextClassInfo = propertyInfo.ElementClassInfo;
                    object        nextValue     = state.Current.Enumerator.Current;
                    state.Push(nextClassInfo, nextValue);
                }

                return(false);
            }

            // We are done enumerating.
            writer.WriteEndArray();

            if (state.Current.PopStackOnEndArray)
            {
                state.Pop();
            }
            else
            {
                state.Current.EndArray();
            }

            return(true);
        }
Пример #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);
            }

            // 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);
        }
Пример #4
0
        internal bool TryWriteDataExtensionProperty(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state)
        {
            Debug.Assert(value != null);

            if (!IsInternalConverter)
            {
                return(TryWrite(writer, value, options, ref state));
            }

            Debug.Assert(this is JsonDictionaryConverter <T>);

            state.Current.PolymorphicJsonPropertyInfo = state.Current.DeclaredJsonPropertyInfo !.RuntimeClassInfo.ElementClassInfo !.PropertyInfoForClassInfo;

            if (writer.CurrentDepth >= options.EffectiveMaxDepth)
            {
                ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth);
            }

            JsonDictionaryConverter <T> dictionaryConverter = (JsonDictionaryConverter <T>) this;

            bool isContinuation = state.IsContinuation;
            bool success;

            state.Push();

            if (!isContinuation)
            {
                Debug.Assert(state.Current.OriginalDepth == 0);
                state.Current.OriginalDepth = writer.CurrentDepth;
            }

            // Ignore the naming policy for extension data.
            state.Current.IgnoreDictionaryKeyPolicy = true;

            success = dictionaryConverter.OnWriteResume(writer, value, options, ref state);
            if (success)
            {
                VerifyWrite(state.Current.OriginalDepth, writer);
            }

            state.Pop(success);

            return(success);
        }
Пример #5
0
        private static bool WriteObject(
            JsonSerializerOptions options,
            ref Utf8JsonWriter writer,
            ref WriteStack state)
        {
            JsonClassInfo classInfo = state.Current.JsonClassInfo;

            // Write the start.
            if (!state.Current.StartObjectWritten)
            {
                if (state.Current.JsonPropertyInfo?._escapedName == null)
                {
                    writer.WriteStartObject();
                }
                else
                {
                    writer.WriteStartObject(state.Current.JsonPropertyInfo._escapedName);
                }
                state.Current.StartObjectWritten = true;
            }

            // Determine if we are done enumerating properties.
            if (state.Current.PropertyIndex != classInfo.PropertyCount)
            {
                HandleObject(options, ref writer, ref state);
                return(false);
            }

            writer.WriteEndObject();

            if (state.Current.PopStackOnEndObject)
            {
                state.Pop();
            }
            else
            {
                state.Current.EndObject();
            }

            return(true);
        }
        private static bool HandleEnumerable(
            JsonClassInfo elementClassInfo,
            JsonSerializerOptions options,
            ref Utf8JsonWriter writer,
            ref WriteStack state)
        {
            Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable);

            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            if (state.Current.Enumerator == null)
            {
                if (jsonPropertyInfo._name == null)
                {
                    writer.WriteStartArray();
                }
                else
                {
                    writer.WriteStartArray(jsonPropertyInfo._name);
                }

                IEnumerable enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue, options);

                if (enumerable != null)
                {
                    state.Current.Enumerator = enumerable.GetEnumerator();
                }
            }

            if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext())
            {
                // Check for polymorphism.
                if (elementClassInfo.ClassType == ClassType.Unknown)
                {
                    object currentValue = state.Current.Enumerator.Current;
                    GetRuntimeClassInfo(currentValue, ref elementClassInfo, options);
                }

                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer);
                }
                else if (state.Current.Enumerator.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.Enumerator.Current;
                    state.Push(elementClassInfo, nextValue);
                }

                return(false);
            }

            // We are done enumerating.
            writer.WriteEndArray();

            if (state.Current.PopStackOnEndArray)
            {
                state.Pop();
            }
            else
            {
                state.Current.EndArray();
            }

            return(true);
        }
Пример #7
0
        internal bool TryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, ref WriteStack state)
        {
            if (writer.CurrentDepth >= options.EffectiveMaxDepth)
            {
                ThrowHelper.ThrowJsonException_SerializerCycleDetected(options.EffectiveMaxDepth);
            }

            if (CanBePolymorphic)
            {
                if (value == null)
                {
                    if (!HandleNull)
                    {
                        writer.WriteNullValue();
                    }
                    else
                    {
                        Debug.Assert(ClassType == ClassType.Value);
                        Debug.Assert(!state.IsContinuation);

                        int originalPropertyDepth = writer.CurrentDepth;
                        Write(writer, value, options);
                        VerifyWrite(originalPropertyDepth, writer);
                    }

                    return(true);
                }

                Type type = value.GetType();
                if (type == typeof(object))
                {
                    writer.WriteStartObject();
                    writer.WriteEndObject();
                    return(true);
                }

                if (type != TypeToConvert)
                {
                    // Handle polymorphic case and get the new converter.
                    JsonConverter jsonConverter = state.Current.InitializeReEntry(type, options);
                    if (jsonConverter != this)
                    {
                        // We found a different converter; forward to that.
                        return(jsonConverter.TryWriteAsObject(writer, value, options, ref state));
                    }
                }
            }
            else if (value == null && !HandleNull)
            {
                // We do not pass null values to converters unless HandleNull is true. Null values for properties were
                // already handled in GetMemberAndWriteJson() so we don't need to check for IgnoreNullValues here.
                writer.WriteNullValue();
                return(true);
            }

            if (ClassType == ClassType.Value)
            {
                Debug.Assert(!state.IsContinuation);

                int originalPropertyDepth = writer.CurrentDepth;

                Write(writer, value, options);
                VerifyWrite(originalPropertyDepth, writer);
                return(true);
            }

            bool isContinuation = state.IsContinuation;

            state.Push();

            if (!isContinuation)
            {
                Debug.Assert(state.Current.OriginalDepth == 0);
                state.Current.OriginalDepth = writer.CurrentDepth;
            }

            bool success = OnTryWrite(writer, value, options, ref state);

            if (success)
            {
                VerifyWrite(state.Current.OriginalDepth, writer);
                // No need to clear state.Current.OriginalDepth since a stack pop will occur.
            }

            state.Pop(success);

            return(success);
        }
        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 = 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);
        }
Пример #9
0
        private static bool HandleEnumerable(
            JsonClassInfo elementClassInfo,
            JsonSerializerOptions options,
            ref Utf8JsonWriter writer,
            ref WriteStack state)
        {
            Debug.Assert(state.Current.JsonPropertyInfo.ClassType == ClassType.Enumerable);

            JsonPropertyInfo jsonPropertyInfo = state.Current.JsonPropertyInfo;

            if (state.Current.Enumerator == null)
            {
                if (jsonPropertyInfo._name == null)
                {
                    writer.WriteStartArray();
                }
                else
                {
                    writer.WriteStartArray(jsonPropertyInfo._name);
                }

                IEnumerable enumerable = (IEnumerable)jsonPropertyInfo.GetValueAsObject(state.Current.CurrentValue, options);

                if (enumerable != null)
                {
                    state.Current.Enumerator = enumerable.GetEnumerator();
                }
            }

            if (state.Current.Enumerator != null && state.Current.Enumerator.MoveNext())
            {
                // If the enumerator contains typeof(object), get the run-time type
                if (elementClassInfo.ClassType == ClassType.Object && jsonPropertyInfo.ElementClassInfo.Type == typeof(object))
                {
                    object currentValue = state.Current.Enumerator.Current;
                    if (currentValue != null)
                    {
                        Type runtimeType = currentValue.GetType();

                        // Ignore object() instances since they are handled as an empty object.
                        if (runtimeType != typeof(object))
                        {
                            elementClassInfo = options.GetOrAddClass(runtimeType);
                        }
                    }
                }

                if (elementClassInfo.ClassType == ClassType.Value)
                {
                    elementClassInfo.GetPolicyProperty().WriteEnumerable(options, ref state.Current, ref writer);
                }
                else if (state.Current.Enumerator.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.Enumerator.Current;
                    state.Push(elementClassInfo, nextValue);
                }

                return(false);
            }

            // We are done enumerating.
            writer.WriteEndArray();

            if (state.Current.PopStackOnEndArray)
            {
                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 (!jsonPropertyInfo.ShouldSerialize)
            {
                // Ignore writing this property.
                return(true);
            }

            if (state.Current.Enumerator == null)
            {
                // Verify that the Dictionary can be serialized by having <string> as first generic argument.
                Type[] args = jsonPropertyInfo.RuntimePropertyType.GetGenericArguments();
                if (args.Length == 0 || args[0].UnderlyingSystemType != typeof(string))
                {
                    ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(state.Current.JsonClassInfo.Type, state.PropertyPath);
                }

                IEnumerable 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 = enumerable.GetEnumerator();
                state.Current.WriteObjectOrArrayStart(ClassType.Dictionary, writer);
            }

            if (state.Current.Enumerator.MoveNext())
            {
                // 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(options, 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);
        }