Move JsonSerializerOptions initialization logic to a shared helper. (#89729)
authorEirik Tsarpalis <eirik.tsarpalis@gmail.com>
Mon, 31 Jul 2023 20:33:37 +0000 (23:33 +0300)
committerGitHub <noreply@github.com>
Mon, 31 Jul 2023 20:33:37 +0000 (23:33 +0300)
src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/HttpContentJsonExtensions.AsyncEnumerable.cs
src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonContent.cs
src/libraries/System.Net.Http.Json/src/System/Net/Http/Json/JsonHelpers.cs
src/libraries/System.Net.Http.Json/tests/FunctionalTests/HttpContentJsonExtensionsTests.cs

index c42f51d..9ea8023 100644 (file)
@@ -67,11 +67,7 @@ namespace System.Net.Http.Json
             JsonSerializerOptions? options,
             CancellationToken cancellationToken)
         {
-            options ??= JsonSerializerOptions.Default;
-            options.MakeReadOnly();
-
-            var jsonTypeInfo = (JsonTypeInfo<TValue>)options.GetTypeInfo(typeof(TValue));
-
+            var jsonTypeInfo = (JsonTypeInfo<TValue>)JsonHelpers.GetJsonTypeInfo(typeof(TValue), options);
             return ReadFromJsonAsAsyncEnumerableCore(content, jsonTypeInfo, cancellationToken);
         }
 
index 08573d5..6cb464d 100644 (file)
@@ -35,7 +35,7 @@ namespace System.Net.Http.Json
         [RequiresUnreferencedCode(HttpContentJsonExtensions.SerializationUnreferencedCodeMessage)]
         [RequiresDynamicCode(HttpContentJsonExtensions.SerializationDynamicCodeMessage)]
         public static JsonContent Create<T>(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 @@ namespace System.Net.Http.Json
             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>(T? inputValue, JsonTypeInfo<T> jsonTypeInfo,
@@ -136,20 +136,6 @@ namespace System.Net.Http.Json
             }
         }
 
-        [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()))
index f2781f8..32672b9 100644 (file)
@@ -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 @@ namespace System.Net.Http.Json
     {
         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)
index 6d2be61..57b4588 100644 (file)
@@ -134,6 +134,33 @@ namespace System.Net.Http.Json.Functional.Tests
         }
 
         [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<Person>())
+                        {
+                            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()
         {
             await HttpMessageHandlerLoopbackServer.CreateClientAndServerAsync(