Merged PR 7268: Avoid caching JsonSerializer
Avoid caching JsonSerializer
This commit is contained in:
parent
1aa1069bbf
commit
8d09403118
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.Formatters.Json" />
|
||||
<Reference Include="Microsoft.AspNetCore.Mvc.TestCommon" />
|
||||
|
||||
<Reference Include="Microsoft.AspNetCore.Http" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue