diff options
author | Pranav Krishnamoorthy <prkrishn@microsoft.com> | 2020-04-14 20:49:57 +0300 |
---|---|---|
committer | Pranav Krishnamoorthy <prkrishn@microsoft.com> | 2020-04-14 20:49:57 +0300 |
commit | 8d09403118ca5d3d972b599b50f942be359a9a49 (patch) | |
tree | 00969df497693e00e4a7b9d85ef7615f6fb3562d | |
parent | 1aa1069bbf3f77a38306ab5f483597268a49b073 (diff) |
Merged PR 7268: Avoid caching JsonSerializerv2.1.18
Avoid caching JsonSerializer
4 files changed, 79 insertions, 8 deletions
diff --git a/eng/PatchConfig.props b/eng/PatchConfig.props index 46ef4cd3c4..4e0ba9c955 100644 --- a/eng/PatchConfig.props +++ b/eng/PatchConfig.props @@ -62,6 +62,7 @@ Later on, this will be checked using this condition: </PropertyGroup> <PropertyGroup Condition=" '$(VersionPrefix)' == '2.1.18' "> <PackagesInPatch> + Microsoft.AspNetCore.Mvc.Formatters.Json; </PackagesInPatch> </PropertyGroup> </Project> diff --git a/src/Mvc/Mvc.Formatters.Json/src/JsonOutputFormatter.cs b/src/Mvc/Mvc.Formatters.Json/src/JsonOutputFormatter.cs index 744d558680..bab47261d7 100644 --- a/src/Mvc/Mvc.Formatters.Json/src/JsonOutputFormatter.cs +++ b/src/Mvc/Mvc.Formatters.Json/src/JsonOutputFormatter.cs @@ -18,10 +18,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters public class JsonOutputFormatter : TextOutputFormatter { private readonly IArrayPool<char> _charPool; - - // Perf: JsonSerializers are relatively expensive to create, and are thread safe. We cache - // the serializer and invalidate it when the settings change. - private JsonSerializer _serializer; + private JsonSerializerSettings _serializerSettings; /// <summary> /// Initializes a new <see cref="JsonOutputFormatter"/> instance. @@ -121,12 +118,12 @@ namespace Microsoft.AspNetCore.Mvc.Formatters /// <returns>The <see cref="JsonSerializer"/> used during serialization and deserialization.</returns> protected virtual JsonSerializer CreateJsonSerializer() { - if (_serializer == null) + if (_serializerSettings == null) { - _serializer = JsonSerializer.Create(SerializerSettings); + _serializerSettings = ShallowCopy(SerializerSettings); } - return _serializer; + return JsonSerializer.Create(_serializerSettings); } /// <inheritdoc /> @@ -153,5 +150,43 @@ namespace Microsoft.AspNetCore.Mvc.Formatters await writer.FlushAsync(); } } + + private static JsonSerializerSettings ShallowCopy(JsonSerializerSettings settings) + { + var copiedSettings = new JsonSerializerSettings + { + FloatParseHandling = settings.FloatParseHandling, + FloatFormatHandling = settings.FloatFormatHandling, + DateParseHandling = settings.DateParseHandling, + DateTimeZoneHandling = settings.DateTimeZoneHandling, + DateFormatHandling = settings.DateFormatHandling, + Formatting = settings.Formatting, + MaxDepth = settings.MaxDepth, + DateFormatString = settings.DateFormatString, + Context = settings.Context, + Error = settings.Error, + SerializationBinder = settings.SerializationBinder, + TraceWriter = settings.TraceWriter, + Culture = settings.Culture, + ReferenceResolverProvider = settings.ReferenceResolverProvider, + EqualityComparer = settings.EqualityComparer, + ContractResolver = settings.ContractResolver, + ConstructorHandling = settings.ConstructorHandling, + TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling, + MetadataPropertyHandling = settings.MetadataPropertyHandling, + TypeNameHandling = settings.TypeNameHandling, + PreserveReferencesHandling = settings.PreserveReferencesHandling, + Converters = settings.Converters, + DefaultValueHandling = settings.DefaultValueHandling, + NullValueHandling = settings.NullValueHandling, + ObjectCreationHandling = settings.ObjectCreationHandling, + MissingMemberHandling = settings.MissingMemberHandling, + ReferenceLoopHandling = settings.ReferenceLoopHandling, + CheckAdditionalContent = settings.CheckAdditionalContent, + StringEscapeHandling = settings.StringEscapeHandling, + }; + + return copiedSettings; + } } } diff --git a/src/Mvc/Mvc.Formatters.Json/test/JsonOutputFormatterTests.cs b/src/Mvc/Mvc.Formatters.Json/test/JsonOutputFormatterTests.cs index 15e735a328..595ebc426d 100644 --- a/src/Mvc/Mvc.Formatters.Json/test/JsonOutputFormatterTests.cs +++ b/src/Mvc/Mvc.Formatters.Json/test/JsonOutputFormatterTests.cs @@ -403,7 +403,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters { // Arrange var formatter = new JsonOutputFormatter(new JsonSerializerSettings(), ArrayPool<char>.Shared); - + var body = new MemoryStream(); var actionContext = GetActionContext(MediaTypeHeaderValue.Parse(mediaType), body); var outputFormatterContext = new OutputFormatterWriteContext( @@ -425,6 +425,40 @@ namespace Microsoft.AspNetCore.Mvc.Formatters Assert.Equal(new StringSegment(expectedContentType), outputFormatterContext.ContentType); } + [Fact] + public async Task SerializingWithPreserveReferenceHandling() + { + // Arrange + var expected = "{\"$id\":\"1\",\"fullName\":\"John\",\"age\":35}"; + var user = new User { FullName = "John", age = 35 }; + + var settings = new JsonSerializerSettings + { + ContractResolver = new DefaultContractResolver + { + NamingStrategy = new CamelCaseNamingStrategy(), + }, + PreserveReferencesHandling = PreserveReferencesHandling.All, + }; + var formatter = new TestableJsonOutputFormatter(settings); + + for (var i = 0; i < 3; i++) + { + // Act + var context = GetOutputFormatterContext(user, typeof(User)); + await formatter.WriteResponseBodyAsync(context, Encoding.UTF8); + + // Assert + var body = context.HttpContext.Response.Body; + + Assert.NotNull(body); + body.Position = 0; + + var content = new StreamReader(body, Encoding.UTF8).ReadToEnd(); + Assert.Equal(expected, content); + } + } + private static Encoding CreateOrGetSupportedEncoding( JsonOutputFormatter formatter, string encodingAsString, diff --git a/src/Mvc/Mvc.Formatters.Json/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj b/src/Mvc/Mvc.Formatters.Json/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj index 6bea21ef4e..dc89f857d6 100644 --- a/src/Mvc/Mvc.Formatters.Json/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj +++ b/src/Mvc/Mvc.Formatters.Json/test/Microsoft.AspNetCore.Mvc.Formatters.Json.Test.csproj @@ -5,6 +5,7 @@ </PropertyGroup> <ItemGroup> + <Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" /> <Reference Include="Microsoft.AspNetCore.Mvc.TestCommon" /> <Reference Include="Microsoft.AspNetCore.Http" /> |