Skip to content

Commit 322735d

Browse files
[Json] Avoid writing to PipeWriter if IAsyncEnumerable throws before first item (#113503)
* [Json] Avoid writing to PipeWriter if IAsyncEnumerable throws before first item * update
1 parent f94a27b commit 322735d

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonTypeInfoOfT.WriteHelpers.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ rootValue is not null &&
169169
try
170170
{
171171
isFinalBlock = EffectiveConverter.WriteCore(writer, rootValue, Options, ref state);
172-
writer.Flush();
173172

174173
if (state.SuppressFlush)
175174
{
@@ -179,6 +178,7 @@ rootValue is not null &&
179178
}
180179
else
181180
{
181+
writer.Flush();
182182
FlushResult result = await pipeWriter.FlushAsync(cancellationToken).ConfigureAwait(false);
183183
if (result.IsCanceled || result.IsCompleted)
184184
{
@@ -230,6 +230,9 @@ rootValue is not null &&
230230
}
231231
catch
232232
{
233+
// Reset the writer in exception cases as we don't want the writer.Dispose() call to flush any pending bytes.
234+
writer.Reset();
235+
writer.Dispose();
233236
// On exception, walk the WriteStack for any orphaned disposables and try to dispose them.
234237
await state.DisposePendingDisposablesOnExceptionAsync().ConfigureAwait(false);
235238
throw;

src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/JsonSerializerWrapper.Reflection.cs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -886,11 +886,13 @@ private int ReadExactlyFromSource(byte[] buffer, int offset, int count)
886886
}
887887

888888
// TODO: Deserialize to use PipeReader overloads once implemented
889-
private class AsyncPipelinesSerializerWrapper : JsonSerializerWrapper
889+
private class AsyncPipelinesSerializerWrapper : StreamingJsonSerializerWrapper
890890
{
891891
public override JsonSerializerOptions DefaultOptions => JsonSerializerOptions.Default;
892892
public override bool SupportsNullValueOnDeserialize => true;
893893

894+
public override bool IsAsyncSerializer => true;
895+
894896
public override async Task<T> DeserializeWrapper<T>(string json, JsonSerializerOptions options = null)
895897
{
896898
return await JsonSerializer.DeserializeAsync<T>(new MemoryStream(Encoding.UTF8.GetBytes(json)), options);
@@ -915,6 +917,31 @@ public override async Task<object> DeserializeWrapper(string json, Type type, Js
915917
return await JsonSerializer.DeserializeAsync(new MemoryStream(Encoding.UTF8.GetBytes(json)), type, context);
916918
}
917919

920+
public override Task<object> DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerOptions? options = null)
921+
{
922+
return JsonSerializer.DeserializeAsync(utf8Json, returnType, options).AsTask();
923+
}
924+
925+
public override Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonSerializerOptions? options = null)
926+
{
927+
return JsonSerializer.DeserializeAsync<T>(utf8Json, options).AsTask();
928+
}
929+
930+
public override Task<object> DeserializeWrapper(Stream utf8Json, Type returnType, JsonSerializerContext context)
931+
{
932+
return JsonSerializer.DeserializeAsync(utf8Json, returnType, context).AsTask();
933+
}
934+
935+
public override Task<T> DeserializeWrapper<T>(Stream utf8Json, JsonTypeInfo<T> jsonTypeInfo)
936+
{
937+
return JsonSerializer.DeserializeAsync(utf8Json, jsonTypeInfo).AsTask();
938+
}
939+
940+
public override Task<object> DeserializeWrapper(Stream utf8Json, JsonTypeInfo jsonTypeInfo)
941+
{
942+
return JsonSerializer.DeserializeAsync(utf8Json, jsonTypeInfo).AsTask();
943+
}
944+
918945
public override async Task<string> SerializeWrapper(object value, Type inputType, JsonSerializerOptions options = null)
919946
{
920947
Pipe pipe = new Pipe();
@@ -969,6 +996,71 @@ public override async Task<string> SerializeWrapper(object value, JsonTypeInfo j
969996
pipe.Reader.AdvanceTo(result.Buffer.End);
970997
return stringResult;
971998
}
999+
1000+
public override async Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerOptions? options = null)
1001+
{
1002+
var writer = PipeWriter.Create(stream);
1003+
try
1004+
{
1005+
await JsonSerializer.SerializeAsync(writer, value, inputType, options);
1006+
}
1007+
finally
1008+
{
1009+
await writer.FlushAsync();
1010+
}
1011+
}
1012+
1013+
public override async Task SerializeWrapper<T>(Stream stream, T value, JsonSerializerOptions? options = null)
1014+
{
1015+
var writer = PipeWriter.Create(stream);
1016+
try
1017+
{
1018+
await JsonSerializer.SerializeAsync(writer, value, options);
1019+
}
1020+
finally
1021+
{
1022+
await writer.FlushAsync();
1023+
}
1024+
}
1025+
1026+
public override async Task SerializeWrapper(Stream stream, object value, Type inputType, JsonSerializerContext context)
1027+
{
1028+
var writer = PipeWriter.Create(stream);
1029+
try
1030+
{
1031+
await JsonSerializer.SerializeAsync(writer, value, inputType, context);
1032+
}
1033+
finally
1034+
{
1035+
await writer.FlushAsync();
1036+
}
1037+
}
1038+
1039+
public override async Task SerializeWrapper<T>(Stream stream, T value, JsonTypeInfo<T> jsonTypeInfo)
1040+
{
1041+
var writer = PipeWriter.Create(stream);
1042+
try
1043+
{
1044+
await JsonSerializer.SerializeAsync(writer, value, jsonTypeInfo);
1045+
}
1046+
finally
1047+
{
1048+
await writer.FlushAsync();
1049+
}
1050+
}
1051+
1052+
public override async Task SerializeWrapper(Stream stream, object value, JsonTypeInfo jsonTypeInfo)
1053+
{
1054+
var writer = PipeWriter.Create(stream);
1055+
try
1056+
{
1057+
await JsonSerializer.SerializeAsync(writer, value, jsonTypeInfo);
1058+
}
1059+
finally
1060+
{
1061+
await writer.FlushAsync();
1062+
}
1063+
}
9721064
}
9731065
}
9741066
}

0 commit comments

Comments
 (0)