diff options
author | Pranav Krishnamoorthy <prkrishn@microsoft.com> | 2020-06-10 01:29:56 +0300 |
---|---|---|
committer | Pranav Krishnamoorthy <prkrishn@microsoft.com> | 2020-06-10 01:29:56 +0300 |
commit | 7217163881608f82ca4b2d2f02e4c0f6316275c6 (patch) | |
tree | eb2d497a99b25a33e3acdc13f808398a47292628 | |
parent | 627eef52715dc8e58aa0833c0b796f7cc9627610 (diff) |
Merged PR 8354: Merged PR 7268: Avoid caching JsonSerializerv2.2.11
Merged PR 7268: Avoid caching JsonSerializer
Avoid caching JsonSerializer
2.1 commit that was cherry-picked: https://github.com/dotnet/aspnetcore/commit/8d09403118ca5d3d972b599b50f942be359a9a49
-rw-r--r-- | eng/PatchConfig.props | 1 | ||||
-rw-r--r-- | src/Mvc/Mvc.Formatters.Json/src/JsonOutputFormatter.cs | 49 | ||||
-rw-r--r-- | src/Mvc/Mvc.Formatters.Json/test/JsonOutputFormatterTests.cs | 36 |
3 files changed, 78 insertions, 8 deletions
diff --git a/eng/PatchConfig.props b/eng/PatchConfig.props index 087130c920..64cc0ab5c6 100644 --- a/eng/PatchConfig.props +++ b/eng/PatchConfig.props @@ -97,6 +97,7 @@ Later on, this will be checked using this condition: </PropertyGroup> <PropertyGroup Condition=" '$(VersionPrefix)' == '2.2.11' "> <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, |