Pool JsonSerializer for Output formatting
This commit is contained in:
parent
ccfd235f50
commit
e75eebbed0
|
|
@ -17,6 +17,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
||||||
{
|
{
|
||||||
private JsonSerializerSettings _serializerSettings;
|
private JsonSerializerSettings _serializerSettings;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
public JsonOutputFormatter()
|
public JsonOutputFormatter()
|
||||||
: this(SerializerSettingsProvider.CreateSerializerSettings())
|
: this(SerializerSettingsProvider.CreateSerializerSettings())
|
||||||
{
|
{
|
||||||
|
|
@ -40,6 +44,10 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the <see cref="JsonSerializerSettings"/> used to configure the <see cref="JsonSerializer"/>.
|
/// Gets or sets the <see cref="JsonSerializerSettings"/> used to configure the <see cref="JsonSerializer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Any modifications to the <see cref="JsonSerializerSettings"/> object after this
|
||||||
|
/// <see cref="JsonOutputFormatter"/> has been used will have no effect.
|
||||||
|
/// </remarks>
|
||||||
public JsonSerializerSettings SerializerSettings
|
public JsonSerializerSettings SerializerSettings
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -54,6 +62,9 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
||||||
}
|
}
|
||||||
|
|
||||||
_serializerSettings = value;
|
_serializerSettings = value;
|
||||||
|
|
||||||
|
// If the settings change, then invalidate the cached serializer.
|
||||||
|
_serializer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,7 +106,12 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
||||||
/// <returns>The <see cref="JsonSerializer"/> used during serialization and deserialization.</returns>
|
/// <returns>The <see cref="JsonSerializer"/> used during serialization and deserialization.</returns>
|
||||||
protected virtual JsonSerializer CreateJsonSerializer()
|
protected virtual JsonSerializer CreateJsonSerializer()
|
||||||
{
|
{
|
||||||
return JsonSerializer.Create(SerializerSettings);
|
if (_serializer == null)
|
||||||
|
{
|
||||||
|
_serializer = JsonSerializer.Create(SerializerSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _serializer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
public override Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.AspNet.Http;
|
using Microsoft.AspNet.Http;
|
||||||
using Microsoft.AspNet.Http.Internal;
|
using Microsoft.AspNet.Http.Internal;
|
||||||
using Microsoft.AspNet.Mvc.Abstractions;
|
using Microsoft.AspNet.Mvc.Abstractions;
|
||||||
|
using Microsoft.AspNet.Mvc.Internal;
|
||||||
using Microsoft.AspNet.Routing;
|
using Microsoft.AspNet.Routing;
|
||||||
using Microsoft.AspNet.Testing;
|
using Microsoft.AspNet.Testing;
|
||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
|
|
@ -74,6 +75,79 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
||||||
Assert.Equal(expectedOutput, content);
|
Assert.Equal(expectedOutput, content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ChangesTo_DefaultSerializerSettings_AfterSerialization_NoEffect()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var person = new User() { Name = "John", Age = 35 };
|
||||||
|
var expectedOutput = JsonConvert.SerializeObject(
|
||||||
|
person,
|
||||||
|
SerializerSettingsProvider.CreateSerializerSettings());
|
||||||
|
|
||||||
|
var jsonFormatter = new JsonOutputFormatter();
|
||||||
|
|
||||||
|
// This will create a serializer - which gets cached.
|
||||||
|
var outputFormatterContext1 = GetOutputFormatterContext(person, typeof(User));
|
||||||
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext1);
|
||||||
|
|
||||||
|
// These changes should have no effect.
|
||||||
|
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
|
||||||
|
jsonFormatter.SerializerSettings.Formatting = Formatting.Indented;
|
||||||
|
|
||||||
|
var outputFormatterContext2 = GetOutputFormatterContext(person, typeof(User));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var body = outputFormatterContext2.HttpContext.Response.Body;
|
||||||
|
|
||||||
|
Assert.NotNull(body);
|
||||||
|
body.Position = 0;
|
||||||
|
|
||||||
|
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal(expectedOutput, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ReplaceSerializerSettings_AfterSerialization_TakesEffect()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var person = new User() { Name = "John", Age = 35 };
|
||||||
|
var expectedOutput = JsonConvert.SerializeObject(person, new JsonSerializerSettings()
|
||||||
|
{
|
||||||
|
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||||
|
Formatting = Formatting.Indented
|
||||||
|
});
|
||||||
|
|
||||||
|
var jsonFormatter = new JsonOutputFormatter();
|
||||||
|
|
||||||
|
// This will create a serializer - which gets cached.
|
||||||
|
var outputFormatterContext1 = GetOutputFormatterContext(person, typeof(User));
|
||||||
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext1);
|
||||||
|
|
||||||
|
// This results in a new serializer being created.
|
||||||
|
jsonFormatter.SerializerSettings = new JsonSerializerSettings()
|
||||||
|
{
|
||||||
|
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||||
|
Formatting = Formatting.Indented,
|
||||||
|
};
|
||||||
|
|
||||||
|
var outputFormatterContext2 = GetOutputFormatterContext(person, typeof(User));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
await jsonFormatter.WriteResponseBodyAsync(outputFormatterContext2);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var body = outputFormatterContext2.HttpContext.Response.Body;
|
||||||
|
|
||||||
|
Assert.NotNull(body);
|
||||||
|
body.Position = 0;
|
||||||
|
|
||||||
|
var content = new StreamReader(body, Encoding.UTF8).ReadToEnd();
|
||||||
|
Assert.Equal(expectedOutput, content);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task CustomSerializerSettingsObject_TakesEffect()
|
public async Task CustomSerializerSettingsObject_TakesEffect()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue