diff --git a/src/FluentHttpClient.Tests/IntegrationTests.cs b/src/FluentHttpClient.Tests/IntegrationTests.cs new file mode 100644 index 0000000..efaa902 --- /dev/null +++ b/src/FluentHttpClient.Tests/IntegrationTests.cs @@ -0,0 +1,31 @@ +namespace FluentHttpClient.Tests; + +public class IntegrationTests +{ + [Fact] + public async Task ReadJsonAsync_ShouldReturnDeserializedObjectMultipleTimes() + { + var client = new HttpClient + { + BaseAddress = new Uri("https://jsonplaceholder.typicode.com") + }; + + var response = await client + .UsingRoute("posts/1") + .GetAsync(); + + var post1 = await response.ReadJsonAsync(); + var post2 = await response.ReadJsonAsync(); + + post1.ShouldNotBeNull(); + post2.ShouldNotBeNull(); + } +} + +public sealed class Post +{ + public int Id { get; set; } + public int UserId { get; set; } + public string? Title { get; set; } + public string? Body { get; set; } +} \ No newline at end of file diff --git a/src/FluentHttpClient/FluentJsonDeserialization.cs b/src/FluentHttpClient/FluentJsonDeserialization.cs index 868166d..83240b0 100644 --- a/src/FluentHttpClient/FluentJsonDeserialization.cs +++ b/src/FluentHttpClient/FluentJsonDeserialization.cs @@ -89,16 +89,16 @@ public static class FluentJsonDeserialization } #if NET5_0_OR_GREATER - var stream = await response.Content - .ReadAsStreamAsync(cancellationToken) + var json = await response.Content + .ReadAsStringAsync(cancellationToken) .ConfigureAwait(false); #else - var stream = await response.Content - .ReadAsStreamAsync() + var json = await response.Content + .ReadAsStringAsync() .ConfigureAwait(false); #endif - return JsonDocument.Parse(stream, documentOptions); + return JsonDocument.Parse(json, documentOptions); } /// diff --git a/src/FluentHttpClient/FluentJsonTypedDeserialization.cs b/src/FluentHttpClient/FluentJsonTypedDeserialization.cs index f7e48e1..8a52e4d 100644 --- a/src/FluentHttpClient/FluentJsonTypedDeserialization.cs +++ b/src/FluentHttpClient/FluentJsonTypedDeserialization.cs @@ -84,25 +84,23 @@ public static partial class FluentJsonTypedDeserialization // NOTE: HttpResponseMessage.Content is never null on modern TFMs, but can be on older platforms. // These checks exist for cross-target safety and are not hit in current test runs. if (response.Content is null) - { return default; - } options ??= FluentJsonSerializer.DefaultJsonSerializerOptions; #if NET5_0_OR_GREATER - var stream = await response.Content - .ReadAsStreamAsync(cancellationToken) + var json = await response.Content + .ReadAsStringAsync(cancellationToken) .ConfigureAwait(false); #else - var stream = await response.Content - .ReadAsStreamAsync() + var json = await response.Content + .ReadAsStringAsync() .ConfigureAwait(false); #endif - return await JsonSerializer - .DeserializeAsync(stream, options, cancellationToken) - .ConfigureAwait(false); + return cancellationToken.IsCancellationRequested + ? throw new OperationCanceledException(cancellationToken) + : JsonSerializer.Deserialize(json, options); } ///