diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.AsyncEnumerable.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.AsyncEnumerable.cs index c42f51db4f7140..9ea80231aafc23 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.AsyncEnumerable.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.AsyncEnumerable.cs @@ -67,11 +67,7 @@ public static partial class HttpContentJsonExtensions JsonSerializerOptions? options, CancellationToken cancellationToken) { - options ??= JsonSerializerOptions.Default; - options.MakeReadOnly(); - - var jsonTypeInfo = (JsonTypeInfo)options.GetTypeInfo(typeof(TValue)); - + var jsonTypeInfo = (JsonTypeInfo)JsonHelpers.GetJsonTypeInfo(typeof(TValue), options); return ReadFromJsonAsAsyncEnumerableCore(content, jsonTypeInfo, cancellationToken); } diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs index 08573d5ffbbcdb..6cb464db10fd06 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs @@ -35,7 +35,7 @@ private JsonContent( [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)] [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)] public static JsonContent Create(T inputValue, MediaTypeHeaderValue? mediaType = null, JsonSerializerOptions? options = null) - => Create(inputValue, GetJsonTypeInfo(typeof(T), options), mediaType); + => Create(inputValue, JsonHelpers.GetJsonTypeInfo(typeof(T), options), mediaType); [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)] [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)] @@ -44,7 +44,7 @@ public static JsonContent Create(object? inputValue, Type inputType, MediaTypeHe ThrowHelper.ThrowIfNull(inputType); EnsureTypeCompatibility(inputValue, inputType); - return new JsonContent(inputValue, GetJsonTypeInfo(inputType, options), mediaType); + return new JsonContent(inputValue, JsonHelpers.GetJsonTypeInfo(inputType, options), mediaType); } public static JsonContent Create(T? inputValue, JsonTypeInfo jsonTypeInfo, @@ -136,20 +136,6 @@ private async Task SerializeToStreamAsyncCore(Stream targetStream, bool async, C } } - [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)] - [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)] - private static JsonTypeInfo GetJsonTypeInfo(Type inputType, JsonSerializerOptions? options) - { - Debug.Assert(inputType is not null); - - // Ensure the options supports the call to GetTypeInfo - options ??= JsonHelpers.s_defaultSerializerOptions; - options.TypeInfoResolver ??= JsonSerializerOptions.Default.TypeInfoResolver; - options.MakeReadOnly(); - - return options.GetTypeInfo(inputType); - } - private static void EnsureTypeCompatibility(object? inputValue, Type inputType) { if (inputValue is not null && !inputType.IsAssignableFrom(inputValue.GetType())) diff --git a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs index f2781f810da371..32672b90c82234 100644 --- a/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs +++ b/src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs @@ -2,9 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Net.Http.Headers; using System.Text; using System.Text.Json; +using System.Text.Json.Serialization.Metadata; namespace System.Net.Http.Json { @@ -12,6 +14,21 @@ internal static class JsonHelpers { internal static readonly JsonSerializerOptions s_defaultSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); + [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)] + [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)] + internal static JsonTypeInfo GetJsonTypeInfo(Type type, JsonSerializerOptions? options) + { + Debug.Assert(type is not null); + + // Resolves JsonTypeInfo metadata using the appropriate JsonSerializerOptions configuration, + // following the semantics of the JsonSerializer reflection methods. + options ??= s_defaultSerializerOptions; + options.TypeInfoResolver ??= JsonSerializerOptions.Default.TypeInfoResolver; + options.MakeReadOnly(); + + return options.GetTypeInfo(type); + } + internal static MediaTypeHeaderValue GetDefaultMediaType() => new("application/json") { CharSet = "utf-8" }; internal static Encoding? GetEncoding(HttpContent content) diff --git a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpContentJsonExtensionsTests.cs b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpContentJsonExtensionsTests.cs index 6d2be61be1a1e9..57b4588668aeb6 100644 --- a/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpContentJsonExtensionsTests.cs +++ b/src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpContentJsonExtensionsTests.cs @@ -133,6 +133,33 @@ await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( server => server.HandleRequestAsync(headers: _headers, content: "null")); } + [Fact] + public async Task HttpContentAsAsyncEnumerableHonorsWebDefaults() + { + await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync( + async (handler, uri) => + { + using (HttpClient client = new HttpClient(handler)) + { + var request = new HttpRequestMessage(HttpMethod.Get, uri); + HttpResponseMessage response = await client.SendAsync(request); + int count = 0; + await foreach (Person? per in response.Content.ReadFromJsonAsAsyncEnumerable()) + { + Assert.NotNull(per); + Assert.NotNull(per.Name); + count++; + } + Assert.Equal(People.PeopleCount, count); + } + }, + async server => + { + string jsonResponse = JsonSerializer.Serialize(People.WomenOfProgramming, JsonOptions.DefaultSerializerOptions); + await server.HandleRequestAsync(headers: _headers, content: jsonResponse); + }); + } + [Fact] public async Task TestReadFromJsonAsAsyncEnumerableNoMessageBodyAsync() {