public override void Write(Utf8JsonWriter writer, TimeSpan?value, JsonSerializerOptions options)
 {
     if (value is null)
     {
         writer.WriteNullValue();
     }
     else
     {
         writer.WriteStringValue(value.Value.ToString("c", CultureInfo.InvariantCulture));
     }
 }
        private static async Task WriteAsyncCore(Stream utf8Json, object?value, Type inputType, JsonSerializerOptions?options, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                options = JsonSerializerOptions.s_defaultOptions;
            }

            JsonWriterOptions writerOptions = options.GetWriterOptions();

            using (var bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize))
                using (var writer = new Utf8JsonWriter(bufferWriter, writerOptions))
                {
                    if (value == null)
                    {
                        writer.WriteNullValue();
                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        return;
                    }

                    if (inputType == null)
                    {
                        inputType = value.GetType();
                    }

                    WriteStack state = default;
                    state.InitializeRoot(inputType, options, supportContinuation: true);

                    bool isFinalBlock;

                    do
                    {
                        // todo: determine best value here
                        // https://github.com/dotnet/runtime/issues/32356
                        state.FlushThreshold = (int)(bufferWriter.Capacity * .9);
                        isFinalBlock         = WriteCore(
                            writer,
                            value,
                            options,
                            ref state,
                            state.Current.JsonClassInfo !.PolicyProperty !.ConverterBase);

                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        bufferWriter.Clear();
                    } while (!isFinalBlock);
                }

            // todo: verify that we do want to call FlushAsync here (or above). It seems like leaving it to the caller would be best.
        }
Esempio n. 3
0
        private static async Task WriteAsyncCore(Stream utf8Json, object?value, Type inputType, JsonSerializerOptions?options, CancellationToken cancellationToken)
        {
            if (options == null)
            {
                options = JsonSerializerOptions.s_defaultOptions;
            }

            JsonWriterOptions writerOptions = options.GetWriterOptions();

            using (var bufferWriter = new PooledByteBufferWriter(options.DefaultBufferSize))
                using (var writer = new Utf8JsonWriter(bufferWriter, writerOptions))
                {
                    if (value == null)
                    {
                        writer.WriteNullValue();
                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        return;
                    }

                    if (inputType == null)
                    {
                        inputType = value.GetType();
                    }

                    WriteStack state = default;
                    if (options.ReferenceHandling.ShouldWritePreservedReferences())
                    {
                        state.ReferenceResolver = new DefaultReferenceResolver(writing: true);
                    }
                    state.Current.Initialize(inputType, options);
                    state.Current.CurrentValue = value;

                    bool isFinalBlock;
                    int  flushThreshold;

                    do
                    {
                        flushThreshold = (int)(bufferWriter.Capacity * .9); //todo: determine best value here

                        isFinalBlock = Write(writer, originalWriterDepth: 0, flushThreshold, options, ref state);
                        writer.Flush();

                        await bufferWriter.WriteToStreamAsync(utf8Json, cancellationToken).ConfigureAwait(false);

                        bufferWriter.Clear();
                    } while (!isFinalBlock);
                }

            // todo: verify that we do want to call FlushAsync here (or above). It seems like leaving it to the caller would be best.
        }
Esempio n. 4
0
        private static TValue?ReadNode <TValue>(JsonNode?node, JsonTypeInfo jsonTypeInfo)
        {
            JsonSerializerOptions options = jsonTypeInfo.Options;

            // For performance, share the same buffer across serialization and deserialization.
            using var output = new PooledByteBufferWriter(options.DefaultBufferSize);
            using (var writer = new Utf8JsonWriter(output, options.GetWriterOptions()))
            {
                if (node is null)
                {
                    writer.WriteNullValue();
                }
                else
                {
                    node.WriteTo(writer, options);
                }
            }

            return(ReadFromSpan <TValue>(output.WrittenMemory.Span, jsonTypeInfo));
        }
        private static void WriteCore(Utf8JsonWriter writer, object?value, Type type, JsonSerializerOptions options)
        {
            Debug.Assert(type != null || value == null);
            Debug.Assert(writer != null);

            if (value == null)
            {
                writer.WriteNullValue();
            }
            else
            {
                //  We treat typeof(object) special and allow polymorphic behavior.
                if (type == typeof(object))
                {
                    type = value.GetType();
                }

                WriteStack state = default;
                state.InitializeRoot(type !, options, supportContinuation: false);
                WriteCore(writer, value, options, ref state, state.Current.JsonClassInfo !.PolicyProperty !.ConverterBase);
            }

            writer.Flush();
        }
        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);
        }
Esempio n. 7
0
        /// <summary>
        ///   Writes this instance to provided writer.
        /// </summary>
        /// <param name="writer">Writer to wrtire this instance to.</param>
        public void WriteTo(Utf8JsonWriter writer)
        {
            var recursionStack = new Stack <RecursionStackFrame>();

            recursionStack.Push(new RecursionStackFrame(null, this));

            while (recursionStack.Any())
            {
                RecursionStackFrame currentFrame = recursionStack.Peek();
                recursionStack.Pop();

                if (currentFrame.PropertyValue == null)
                {
                    // Current object/array is finished.
                    // PropertyValue is null, so we need to check ValueKind:

                    Debug.Assert(currentFrame.ValueKind == JsonValueKind.Object || currentFrame.ValueKind == JsonValueKind.Array);

                    if (currentFrame.ValueKind == JsonValueKind.Object)
                    {
                        writer.WriteEndObject();
                    }
                    if (currentFrame.ValueKind == JsonValueKind.Array)
                    {
                        writer.WriteEndArray();
                    }

                    continue;
                }

                if (currentFrame.PropertyName != null)
                {
                    writer.WritePropertyName(currentFrame.PropertyName);
                }

                switch (currentFrame.PropertyValue)
                {
                case JsonObject jsonObject:
                    writer.WriteStartObject();

                    // Add end of object marker:
                    recursionStack.Push(new RecursionStackFrame(null, null, JsonValueKind.Object));

                    // Add properties to recursion stack. Reverse enumerator to keep properties order:
                    foreach (KeyValuePair <string, JsonNode> jsonProperty in jsonObject.Reverse())
                    {
                        recursionStack.Push(new RecursionStackFrame(jsonProperty.Key, jsonProperty.Value));
                    }
                    break;

                case JsonArray jsonArray:
                    writer.WriteStartArray();

                    // Add end of array marker:
                    recursionStack.Push(new RecursionStackFrame(null, null, JsonValueKind.Array));

                    // Add items to recursion stack. Reverse enumerator to keep items order:
                    foreach (JsonNode item in jsonArray.Reverse())
                    {
                        recursionStack.Push(new RecursionStackFrame(null, item));
                    }
                    break;

                case JsonString jsonString:
                    writer.WriteStringValue(jsonString.Value);
                    break;

                case JsonNumber jsonNumber:
                    writer.WriteNumberValue(Encoding.UTF8.GetBytes(jsonNumber.ToString()));
                    break;

                case JsonBoolean jsonBoolean:
                    writer.WriteBooleanValue(jsonBoolean.Value);
                    break;

                case JsonNull _:
                    writer.WriteNullValue();
                    break;
                }

                writer.Flush();
            }

            writer.Flush();
        }