From edf9174e09ad2385ef50db5a5ea1fecf6d5b3830 Mon Sep 17 00:00:00 2001 From: Eirik Tsarpalis Date: Wed, 23 Feb 2022 18:40:09 +0000 Subject: [PATCH] Fix JsonSerializerOptions.GetConverter reallocating default converters on each call. --- .../JsonSerializerOptions.Converters.cs | 5 ++- .../Text/Json/Serialization/WriteStack.cs | 1 - .../TestClasses/TestClasses.Constructor.cs | 2 ++ .../CustomConverterTests.cs | 32 +++++++++++++------ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs index 6d3a3c88d61647..d30f675462dc32 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerOptions.Converters.cs @@ -159,7 +159,10 @@ internal JsonConverter GetConverterFromMember(Type? parentClassType, Type proper [RequiresUnreferencedCode("Getting a converter for a type may require reflection which depends on unreferenced code.")] public JsonConverter GetConverter(Type typeToConvert!!) { - RootBuiltInConverters(); + if (!IsInitializedForReflectionSerializer) + { + InitializeForReflectionSerializer(); + } return GetConverterInternal(typeToConvert); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs index f966a1a77cb7a0..4b861f31d40676 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs @@ -99,7 +99,6 @@ private void EnsurePushCapacity() public JsonConverter Initialize(Type type, JsonSerializerOptions options, bool supportContinuation) { JsonTypeInfo jsonTypeInfo = options.GetOrAddJsonTypeInfoForRootType(type); - Debug.Assert(options == jsonTypeInfo.Options); return Initialize(jsonTypeInfo, supportContinuation); } diff --git a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs index 890d61f97245d1..ce3ddf1da9a5eb 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs @@ -456,6 +456,8 @@ public class Point_2D : ITestClass [JsonConstructor] public Point_2D(int x, int y) => (X, Y) = (x, y); + public Point_2D() : this(0, 0) { } + public void Initialize() { } public void Verify() diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.cs index 80067292399c46..30852afa0556d1 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.IO; +using Microsoft.DotNet.RemoteExecutor; using Xunit; namespace System.Text.Json.Serialization.Tests @@ -161,19 +163,29 @@ public static void VerifyObjectConverterWithPreservedReferences() Assert.Equal(true, obj); } - [Fact] + [ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] public static void GetConverterRootsBuiltInConverters() { - JsonSerializerOptions options = new(); - RunTest(); - RunTest(); - - void RunTest() + RemoteExecutor.Invoke(static () => { - JsonConverter converter = options.GetConverter(typeof(TConverterReturn)); - Assert.NotNull(converter); - Assert.True(converter is JsonConverter); - } + JsonSerializerOptions options = new(); + RunTest(); + RunTest(); + + void RunTest() where T : new() + { + JsonConverter converter = options.GetConverter(typeof(T)) as JsonConverter; + Assert.NotNull(converter); + + // Should be possible to call into converters that require + // reflection-based metadata + T value = new(); + using var writer = new Utf8JsonWriter(new MemoryStream()); + converter.Write(writer, value, options); + writer.Flush(); + Assert.True(writer.BytesCommitted > 0); + } + }).Dispose(); } [Fact]