private static async Task WriteAsyncInternal(object value, Type type, Stream utf8Stream, JsonSerializerOptions options, CancellationToken cancellationToken) { if (options == null) { options = s_defaultSettings; } var writerState = new JsonWriterState(options.WriterOptions); using (var bufferWriter = new ArrayBufferWriter <byte>(options.EffectiveBufferSize)) { if (value == null) { WriteNull(ref writerState, bufferWriter); #if BUILDING_INBOX_LIBRARY await utf8Stream.WriteAsync(bufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else // todo: stackalloc? await utf8Stream.WriteAsync(bufferWriter.WrittenMemory.ToArray(), 0, bufferWriter.WrittenMemory.Length, cancellationToken).ConfigureAwait(false); #endif return; } if (type == null) { type = value.GetType(); } JsonClassInfo classInfo = options.GetOrAddClass(type); WriteObjectState current = default; current.ClassInfo = classInfo; current.CurrentValue = value; if (classInfo.ClassType != ClassType.Object) { current.PropertyInfo = classInfo.GetPolicyProperty(); } List <WriteObjectState> previous = null; int arrayIndex = 0; bool isFinalBlock; int flushThreshold; do { flushThreshold = (int)(bufferWriter.Capacity * .9); //todo: determine best value here isFinalBlock = Write(ref writerState, bufferWriter, flushThreshold, options, ref current, ref previous, ref arrayIndex); #if BUILDING_INBOX_LIBRARY await utf8Stream.WriteAsync(bufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else // todo: stackalloc? await utf8Stream.WriteAsync(bufferWriter.WrittenMemory.ToArray(), 0, bufferWriter.WrittenMemory.Length, cancellationToken).ConfigureAwait(false); #endif bufferWriter.Clear(); } while (!isFinalBlock); } // todo: do we want to call FlushAsync here (or above)? It seems like leaving it to the caller would be better. //await stream.FlushAsync(cancellationToken).ConfigureAwait(false); }
private static void WriteCore(ArrayBufferWriter <byte> output, object value, Type type, JsonSerializerOptions options) { Debug.Assert(type != null || value == null); var writerState = new JsonWriterState(options.GetWriterOptions()); var writer = new Utf8JsonWriter(output, writerState); 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.Current.Initialize(type, options); state.Current.CurrentValue = value; Write(ref writer, -1, options, ref state); } writer.Flush(isFinalBlock: true); }
private static void WriteCore(ArrayBufferWriter <byte> output, object value, Type type, JsonSerializerOptions options) { Debug.Assert(type != null || value == null); var writerState = new JsonWriterState(options.WriterOptions); var writer = new Utf8JsonWriter(output, writerState); 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; JsonClassInfo classInfo = options.GetOrAddClass(type); state.Current.JsonClassInfo = classInfo; state.Current.CurrentValue = value; if (classInfo.ClassType != ClassType.Object) { state.Current.JsonPropertyInfo = classInfo.GetPolicyProperty(); } Write(ref writer, -1, options, ref state); } writer.Flush(isFinalBlock: true); }
private static void WriteComplexValue( bool indented, string jsonIn, string expectedIndent, string expectedMinimal) { using (ArrayBufferWriter buffer = new ArrayBufferWriter(1024)) using (JsonDocument doc = JsonDocument.Parse($" [ {jsonIn} ]", s_readerOptions)) { JsonElement target = doc.RootElement[0]; var state = new JsonWriterState( new JsonWriterOptions { Indented = indented, }); var writer = new Utf8JsonWriter(buffer, state); target.WriteAsValue(ref writer); writer.Flush(); if (indented && s_replaceNewlines) { AssertContents( expectedIndent.Replace(CompiledNewline, Environment.NewLine), buffer); } AssertContents(indented ? expectedIndent : expectedMinimal, buffer); } }
private static void WriterSystemJsonBasic(bool formatted, bool skipValidation, ArrayFormatterWrapper output, ReadOnlySpan <int> data) { var state = new JsonWriterState(options: new JsonWriterOptions { Indented = formatted, SkipValidation = skipValidation }); var json = new Utf8JsonWriter2(output, state); json.WriteStartObject(); json.WriteNumber("age", 42); json.WriteString("first", "John"); json.WriteString("last", "Smith"); json.WriteStartArray("phoneNumbers"); json.WriteStringValue("425-000-1212"); json.WriteStringValue("425-000-1213"); json.WriteEndArray(); json.WriteStartObject("address"); json.WriteString("street", "1 Microsoft Way"); json.WriteString("city", "Redmond"); json.WriteNumber("zip", 98052); json.WriteEndObject(); json.WriteStartArray("ExtraArray"); for (var i = 0; i < data.Length; i++) { json.WriteNumberValue(data[i]); } json.WriteEndArray(); json.WriteEndObject(); json.Flush(); }
public void WriteToPipeUsingSpan() { string actual = ""; var taskReader = Task.Run(async() => { Json.JsonReaderState state = default; string str = ""; while (true) { ReadResult result = await _pipe.Reader.ReadAsync(); ReadOnlySequence <byte> data = result.Buffer; bool isFinalBlock = result.IsCompleted; (state, str) = ProcessData(data, isFinalBlock, state); _pipe.Reader.AdvanceTo(state.Position); actual += str; if (isFinalBlock) { break; } } }); var taskWriter = Task.Run(async() => { JsonWriterState state = default; long bytesCommitted = 0; while (true) { Memory <byte> memory = new byte [4_000]; (state, bytesCommitted) = WriteData(memory, isFinalBlock: true, state); FlushResult result = await _pipe.Writer.WriteAsync(memory.Slice(0, (int)bytesCommitted)); break; }
public static void WritePropertyOutsideObject(bool skipValidation) { using (ArrayBufferWriter buffer = new ArrayBufferWriter(1024)) using (var doc = JsonDocument.Parse("[ null, false, true, \"hi\", 5, {}, [] ]", s_readerOptions)) { JsonElement root = doc.RootElement; JsonWriterState state = new JsonWriterState( new JsonWriterOptions { SkipValidation = skipValidation, }); const string CharLabel = "char"; byte[] byteUtf8 = Encoding.UTF8.GetBytes("byte"); Utf8JsonWriter writer = new Utf8JsonWriter(buffer, state); if (skipValidation) { foreach (JsonElement val in root.EnumerateArray()) { val.WriteAsProperty(CharLabel.AsSpan(), ref writer); val.WriteAsProperty(byteUtf8, ref writer); } writer.Flush(); AssertContents( "\"char\":null,\"byte\":null," + "\"char\":false,\"byte\":false," + "\"char\":true,\"byte\":true," + "\"char\":\"hi\",\"byte\":\"hi\"," + "\"char\":5,\"byte\":5," + "\"char\":{},\"byte\":{}," + "\"char\":[],\"byte\":[]", buffer); } else { foreach (JsonElement val in root.EnumerateArray()) { JsonTestHelper.AssertThrows <InvalidOperationException>( ref writer, (ref Utf8JsonWriter w) => val.WriteAsProperty(CharLabel.AsSpan(), ref w)); JsonTestHelper.AssertThrows <InvalidOperationException>( ref writer, (ref Utf8JsonWriter w) => val.WriteAsProperty(byteUtf8, ref w)); } JsonTestHelper.AssertThrows <InvalidOperationException>( ref writer, (ref Utf8JsonWriter w) => w.Flush()); writer.Flush(isFinalBlock: false); AssertContents("", buffer); } } }
private static async Task WriteAsyncCore(object value, Type type, Stream utf8Json, JsonSerializerOptions options, CancellationToken cancellationToken) { if (options == null) { options = s_defaultSettings; } var writerState = new JsonWriterState(options.WriterOptions); using (var bufferWriter = new ArrayBufferWriter <byte>(options.EffectiveBufferSize)) { if (value == null) { WriteNull(ref writerState, bufferWriter); #if BUILDING_INBOX_LIBRARY await utf8Json.WriteAsync(bufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else // todo: stackalloc or pool here? await utf8Json.WriteAsync(bufferWriter.WrittenMemory.ToArray(), 0, bufferWriter.WrittenMemory.Length, cancellationToken).ConfigureAwait(false); #endif return; } if (type == null) { type = value.GetType(); } JsonClassInfo classInfo = options.GetOrAddClass(type); WriteStack state = default; state.Current.JsonClassInfo = classInfo; state.Current.CurrentValue = value; if (classInfo.ClassType != ClassType.Object) { state.Current.JsonPropertyInfo = classInfo.GetPolicyProperty(); } bool isFinalBlock; int flushThreshold; do { flushThreshold = (int)(bufferWriter.Capacity * .9); //todo: determine best value here isFinalBlock = Write(ref writerState, bufferWriter, flushThreshold, options, ref state); #if BUILDING_INBOX_LIBRARY await utf8Json.WriteAsync(bufferWriter.WrittenMemory, cancellationToken).ConfigureAwait(false); #else // todo: use pool here to avod extra alloc? await utf8Json.WriteAsync(bufferWriter.WrittenMemory.ToArray(), 0, bufferWriter.WrittenMemory.Length, cancellationToken).ConfigureAwait(false); #endif 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. }
private static void WriteNull( ref JsonWriterState writerState, IBufferWriter <byte> bufferWriter) { Utf8JsonWriter writer = new Utf8JsonWriter(bufferWriter, writerState); writer.WriteNullValue(); writer.Flush(true); }
private static async Task WriteAsyncInternal(object value, Type type, PipeWriter utf8Writer, JsonSerializerOptions options, CancellationToken cancellationToken) { if (options == null) { options = s_defaultSettings; } var writerState = new JsonWriterState(options.WriterOptions); // Allocate the initial buffer. We don't want to use the existing buffer as there may be very few bytes left // and we won't be able to calculate flushThreshold appropriately. Memory <byte> memory = utf8Writer.GetMemory(options.EffectiveBufferSize); if (value == null) { WriteNull(ref writerState, utf8Writer); await utf8Writer.FlushAsync(cancellationToken).ConfigureAwait(false); return; } if (type == null) { type = value.GetType(); } JsonClassInfo classInfo = options.GetOrAddClass(type); WriteObjectState current = default; current.ClassInfo = classInfo; current.CurrentValue = value; if (classInfo.ClassType != ClassType.Object) { current.PropertyInfo = classInfo.GetPolicyProperty(); } List <WriteObjectState> previous = null; int arrayIndex = 0; bool isFinalBlock; // For Pipes there is not a way to get current buffer total size, so we just use the initial memory size. int flushThreshold = (int)(memory.Length * .9); //todo: determine best value here (extensible?) do { isFinalBlock = Write(ref writerState, utf8Writer, flushThreshold, options, ref current, ref previous, ref arrayIndex); await utf8Writer.FlushAsync(cancellationToken).ConfigureAwait(false); } while (!isFinalBlock); }
//[Benchmark] public void WriteArray() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); json.WriteNumberArray(Message, _longs, suppressEscaping: true); json.WriteEndObject(); json.Flush(); }
//[Benchmark] public void WriterSystemTextJsonArrayValues() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); json.WriteNumberArray(Encoding.UTF8.GetBytes("numbers"), dataArray, suppressEscaping: true); json.WriteEndObject(); json.Flush(); }
public static void JsonWriterStateDefaultCtor() { var state = new JsonWriterState(); Assert.Equal(0, state.BytesCommitted); Assert.Equal(0, state.BytesWritten); var expectedOption = new JsonWriterOptions { Indented = false, SkipValidation = false }; Assert.Equal(expectedOption, state.Options); }
private static byte[] WriteInternal(object value, Type type, JsonSerializerOptions options) { if (options == null) { options = s_defaultSettings; } byte[] result; var state = new JsonWriterState(options.WriterOptions); using (var output = new ArrayBufferWriter <byte>(options.EffectiveBufferSize)) { var writer = new Utf8JsonWriter(output, state); if (value == null) { writer.WriteNullValue(); } else { if (type == null) { type = value.GetType(); } WriteObjectState current = default; JsonClassInfo classInfo = options.GetOrAddClass(type); current.ClassInfo = classInfo; current.CurrentValue = value; if (classInfo.ClassType != ClassType.Object) { current.PropertyInfo = classInfo.GetPolicyProperty(); } List <WriteObjectState> previous = null; int arrayIndex = 0; Write(ref writer, -1, options, ref current, ref previous, ref arrayIndex); } writer.Flush(isFinalBlock: true); result = output.WrittenMemory.ToArray(); } return(result); }
public string ToJson() { var state = new JsonWriterState(options: new JsonWriterOptions { Indented = true }); using (var arrayBufferWriter = new ArrayBufferWriter <byte>()) { var writer = new Utf8JsonWriter(arrayBufferWriter, state); writer.WriteStartObject(); if (Version.HasValue) { writer.WriteNumber(propertyName: JsonPropertyVersion, value: Version.Value); } if (IsRoot.HasValue) { writer.WriteBoolean(JsonPropertyIsRoot, IsRoot.Value); } writer.WriteStartObject(JsonPropertyTools); foreach (var tool in Tools) { writer.WriteStartObject(tool.Key); writer.WriteString(JsonPropertyVersion, tool.Value.Version); writer.WriteStartArray(JsonPropertyCommands); foreach (var toolCommandName in tool.Value.Commands) { writer.WriteStringValue(toolCommandName); } writer.WriteEndArray(); writer.WriteEndObject(); } writer.WriteEndObject(); writer.WriteEndObject(); writer.Flush(true); return(Encoding.UTF8.GetString(arrayBufferWriter.WrittenMemory.ToArray())); } }
public static void WriteValueInsideObject(bool skipValidation) { using (ArrayBufferWriter buffer = new ArrayBufferWriter(1024)) using (var doc = JsonDocument.Parse("[ null, false, true, \"hi\", 5, {}, [] ]", s_readerOptions)) { JsonElement root = doc.RootElement; JsonWriterState state = new JsonWriterState( new JsonWriterOptions { SkipValidation = skipValidation, }); Utf8JsonWriter writer = new Utf8JsonWriter(buffer, state); writer.WriteStartObject(); if (skipValidation) { foreach (JsonElement val in root.EnumerateArray()) { val.WriteAsValue(ref writer); } writer.WriteEndObject(); writer.Flush(); AssertContents( "{null,false,true,\"hi\",5,{},[]}", buffer); } else { foreach (JsonElement val in root.EnumerateArray()) { JsonTestHelper.AssertThrows <InvalidOperationException>( ref writer, (ref Utf8JsonWriter w) => val.WriteAsValue(ref w)); } writer.WriteEndObject(); writer.Flush(); AssertContents("{}", buffer); } } }
//[Benchmark] public void WritePropertyValueEscapingRequired() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); for (int i = 0; i < 100; i++) { json.WriteString("fir\nst", "Joh\nn"); } json.WriteEndObject(); json.Flush(); }
//[Benchmark] public void WriteDateTimeUnescapedOverheadUtf16() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); for (int i = 0; i < 100; i++) { json.WriteString("first", MyDate, suppressEscaping: false); } json.WriteEndObject(); json.Flush(); }
//[Benchmark] public void WriterSystemTextJsonBasicUtf8NoDefault() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); for (int i = 0; i < 100; i++) { json.WriteString(First, John); } json.WriteEndObject(); json.Flush(); }
//[Benchmark] public void WriteNumberUnescapedUtf16() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); for (int i = 0; i < 100; i++) { json.WriteNumber("first", value: 123456, suppressEscaping: true); } json.WriteEndObject(); json.Flush(); }
//[Benchmark] public void WritePropertyValueEscapeUnnecessarily() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); for (int i = 0; i < 100; i++) { json.WriteString("first", "John", suppressEscaping: false); } json.WriteEndObject(); json.Flush(); }
private static bool Write( ref JsonWriterState writerState, IBufferWriter <byte> bufferWriter, int flushThreshold, JsonSerializerOptions options, ref WriteStack state) { Utf8JsonWriter writer = new Utf8JsonWriter(bufferWriter, writerState); bool isFinalBlock = Write( ref writer, flushThreshold, options, ref state); writer.Flush(isFinalBlock: isFinalBlock); writerState = writer.GetCurrentState(); return(isFinalBlock); }
//[Benchmark] public void WriteArrayLoop() { _arrayFormatterWrapper.Clear(); var state = new JsonWriterState(options: new JsonWriterOptions { Indented = Formatted, SkipValidation = SkipValidation }); var json = new Utf8JsonWriter2(_arrayFormatterWrapper, state); json.WriteStartObject(); json.WriteStartArray(Message, suppressEscaping: true); for (int i = 0; i < _longs.Length; i++) { json.WriteNumberValue(_longs[i]); } json.WriteEndArray(); json.WriteEndObject(); json.Flush(); }
public void Write(DependencyContext context, Stream stream) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (stream == null) { throw new ArgumentNullException(nameof(stream)); } using (var bufferWriter = new ArrayBufferWriter()) { var state = new JsonWriterState(options: new JsonWriterOptions { Indented = true }); var jsonWriter = new Utf8JsonWriter(bufferWriter, state); WriteCore(context, new UnifiedJsonWriter(jsonWriter)); bufferWriter.CopyTo(stream); } }
private static void WriteSimpleValue(bool indented, string jsonIn, string jsonOut = null) { using (ArrayBufferWriter buffer = new ArrayBufferWriter(1024)) using (JsonDocument doc = JsonDocument.Parse($" [ {jsonIn} ]", s_readerOptions)) { JsonElement target = doc.RootElement[0]; var state = new JsonWriterState( new JsonWriterOptions { Indented = indented, }); var writer = new Utf8JsonWriter(buffer, state); target.WriteAsValue(ref writer); writer.Flush(); AssertContents(jsonOut ?? jsonIn, buffer); } }
private static bool Write( ref JsonWriterState writerState, IBufferWriter <byte> bufferWriter, int flushThreshold, JsonSerializerOptions options, ref WriteObjectState current, ref List <WriteObjectState> previous, ref int arrayIndex) { Utf8JsonWriter writer = new Utf8JsonWriter(bufferWriter, writerState); bool isFinalBlock = Write( ref writer, flushThreshold, options, ref current, ref previous, ref arrayIndex); writer.Flush(isFinalBlock: isFinalBlock); writerState = writer.GetCurrentState(); return(isFinalBlock); }
public override ValueTask Serialize(PipeWriter pipe, string instance, JsonWriterState state = default, CancellationToken cancellationToken = default) { var writer = new Utf8JsonWriter(pipe, state); writer.WriteStringValue(instance, true); return(default);