Use System.Buffers for JSON.NET
This commit is contained in:
parent
5ef839c855
commit
0a9804056e
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Microsoft.AspNet.Mvc.Formatters.Json.Internal
|
||||
{
|
||||
public class JsonArrayPool<T> : IArrayPool<T>
|
||||
{
|
||||
private readonly ArrayPool<T> _inner;
|
||||
|
||||
public JsonArrayPool(ArrayPool<T> inner)
|
||||
{
|
||||
if (inner == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(inner));
|
||||
}
|
||||
|
||||
_inner = inner;
|
||||
}
|
||||
|
||||
public T[] Rent(int minimumLength)
|
||||
{
|
||||
return _inner.Rent(minimumLength);
|
||||
}
|
||||
|
||||
public void Return(T[] array)
|
||||
{
|
||||
if (array == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(array));
|
||||
}
|
||||
|
||||
_inner.Return(array);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding.Validation;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
|
@ -12,22 +13,26 @@ namespace Microsoft.AspNet.Mvc.Formatters.Json.Internal
|
|||
{
|
||||
public class MvcJsonMvcOptionsSetup : ConfigureOptions<MvcOptions>
|
||||
{
|
||||
public MvcJsonMvcOptionsSetup(ILoggerFactory loggerFactory, IOptions<MvcJsonOptions> jsonOptions)
|
||||
: base((_) => ConfigureMvc(_, jsonOptions.Value.SerializerSettings, loggerFactory))
|
||||
public MvcJsonMvcOptionsSetup(
|
||||
ILoggerFactory loggerFactory,
|
||||
IOptions<MvcJsonOptions> jsonOptions,
|
||||
ArrayPool<char> charPool)
|
||||
: base((options) => ConfigureMvc(options, jsonOptions.Value.SerializerSettings, loggerFactory, charPool))
|
||||
{
|
||||
}
|
||||
|
||||
public static void ConfigureMvc(
|
||||
MvcOptions options,
|
||||
JsonSerializerSettings serializerSettings,
|
||||
ILoggerFactory loggerFactory)
|
||||
ILoggerFactory loggerFactory,
|
||||
ArrayPool<char> charPool)
|
||||
{
|
||||
var jsonInputLogger = loggerFactory.CreateLogger<JsonInputFormatter>();
|
||||
var jsonInputPatchLogger = loggerFactory.CreateLogger<JsonPatchInputFormatter>();
|
||||
|
||||
options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings));
|
||||
options.InputFormatters.Add(new JsonInputFormatter(jsonInputLogger, serializerSettings));
|
||||
options.InputFormatters.Add(new JsonPatchInputFormatter(jsonInputPatchLogger, serializerSettings));
|
||||
options.OutputFormatters.Add(new JsonOutputFormatter(serializerSettings, charPool));
|
||||
options.InputFormatters.Add(new JsonInputFormatter(jsonInputLogger, serializerSettings, charPool));
|
||||
options.InputFormatters.Add(new JsonPatchInputFormatter(jsonInputPatchLogger, serializerSettings, charPool));
|
||||
|
||||
options.FormatterMappings.SetMediaTypeMappingForFormat("json", MediaTypeHeaderValue.Parse("application/json"));
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Json.Logging;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
using Microsoft.AspNet.Mvc.ModelBinding;
|
||||
|
|
@ -13,16 +15,22 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
public class JsonInputFormatter : InputFormatter
|
||||
{
|
||||
private JsonSerializerSettings _serializerSettings;
|
||||
private ILogger _logger;
|
||||
private readonly IArrayPool<char> _charPool;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private JsonSerializerSettings _serializerSettings;
|
||||
|
||||
public JsonInputFormatter(ILogger logger)
|
||||
: this(logger, SerializerSettingsProvider.CreateSerializerSettings())
|
||||
: this(logger, SerializerSettingsProvider.CreateSerializerSettings(), ArrayPool<char>.Shared)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings)
|
||||
: this(logger, serializerSettings, ArrayPool<char>.Shared)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool)
|
||||
{
|
||||
if (serializerSettings == null)
|
||||
{
|
||||
|
|
@ -36,6 +44,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
|
||||
_logger = logger;
|
||||
_serializerSettings = serializerSettings;
|
||||
_charPool = new JsonArrayPool<char>(charPool);
|
||||
|
||||
SupportedEncodings.Add(UTF8EncodingWithoutBOM);
|
||||
SupportedEncodings.Add(UTF16EncodingLittleEndian);
|
||||
|
|
@ -84,6 +93,7 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
{
|
||||
using (var jsonReader = new JsonTextReader(streamReader))
|
||||
{
|
||||
jsonReader.ArrayPool = _charPool;
|
||||
jsonReader.CloseInput = false;
|
||||
|
||||
var successful = true;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
|
||||
using Microsoft.AspNet.Mvc.Internal;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
|
|
@ -15,6 +17,8 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
/// </summary>
|
||||
public class JsonOutputFormatter : OutputFormatter
|
||||
{
|
||||
private readonly IArrayPool<char> _charPool;
|
||||
|
||||
private JsonSerializerSettings _serializerSettings;
|
||||
|
||||
// Perf: JsonSerializers are relatively expensive to create, and are thread safe. We cache
|
||||
|
|
@ -22,18 +26,29 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
private JsonSerializer _serializer;
|
||||
|
||||
public JsonOutputFormatter()
|
||||
: this(SerializerSettingsProvider.CreateSerializerSettings())
|
||||
: this(SerializerSettingsProvider.CreateSerializerSettings(), ArrayPool<char>.Shared)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonOutputFormatter(JsonSerializerSettings serializerSettings)
|
||||
: this(serializerSettings, ArrayPool<char>.Shared)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonOutputFormatter(JsonSerializerSettings serializerSettings, ArrayPool<char> charPool)
|
||||
{
|
||||
if (serializerSettings == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serializerSettings));
|
||||
}
|
||||
|
||||
if (charPool == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(charPool));
|
||||
}
|
||||
|
||||
_serializerSettings = serializerSettings;
|
||||
_charPool = new JsonArrayPool<char>(charPool);
|
||||
|
||||
SupportedEncodings.Add(Encoding.UTF8);
|
||||
SupportedEncodings.Add(Encoding.Unicode);
|
||||
|
|
@ -94,8 +109,11 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
throw new ArgumentNullException(nameof(writer));
|
||||
}
|
||||
|
||||
var jsonWriter = new JsonTextWriter(writer);
|
||||
jsonWriter.CloseOutput = false;
|
||||
var jsonWriter = new JsonTextWriter(writer)
|
||||
{
|
||||
ArrayPool = _charPool,
|
||||
CloseOutput = false,
|
||||
};
|
||||
|
||||
return jsonWriter;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNet.JsonPatch;
|
||||
|
|
@ -14,12 +15,15 @@ namespace Microsoft.AspNet.Mvc.Formatters
|
|||
public class JsonPatchInputFormatter : JsonInputFormatter
|
||||
{
|
||||
public JsonPatchInputFormatter(ILogger logger)
|
||||
: this(logger, SerializerSettingsProvider.CreateSerializerSettings())
|
||||
: this(logger, SerializerSettingsProvider.CreateSerializerSettings(), ArrayPool<char>.Shared)
|
||||
{
|
||||
}
|
||||
|
||||
public JsonPatchInputFormatter(ILogger logger, JsonSerializerSettings serializerSettings)
|
||||
: base(logger, serializerSettings)
|
||||
public JsonPatchInputFormatter(
|
||||
ILogger logger,
|
||||
JsonSerializerSettings serializerSettings,
|
||||
ArrayPool<char> charPool)
|
||||
: base(logger, serializerSettings, charPool)
|
||||
{
|
||||
// Clear all values and only include json-patch+json value.
|
||||
SupportedMediaTypes.Clear();
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
"version": "1.0.0-*",
|
||||
"type": "build"
|
||||
},
|
||||
"Newtonsoft.Json": "6.0.6"
|
||||
"Newtonsoft.Json": "8.0.1"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": {},
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
|||
services.TryAdd(ServiceDescriptor.Singleton<JsonOutputFormatter>(serviceProvider =>
|
||||
{
|
||||
var options = serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value;
|
||||
return new JsonOutputFormatter(options.SerializerSettings);
|
||||
var charPool = serviceProvider.GetRequiredService<ArrayPool<char>>();
|
||||
return new JsonOutputFormatter(options.SerializerSettings, charPool);
|
||||
}));
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using Microsoft.AspNet.Mvc.DataAnnotations;
|
||||
using Microsoft.AspNet.Mvc.DataAnnotations.Internal;
|
||||
using Microsoft.AspNet.Mvc.Formatters.Json.Internal;
|
||||
|
|
@ -30,7 +31,7 @@ namespace Microsoft.AspNet.Mvc.IntegrationTests
|
|||
var loggerFactory = new LoggerFactory();
|
||||
var serializerSettings = SerializerSettingsProvider.CreateSerializerSettings();
|
||||
|
||||
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, serializerSettings, loggerFactory);
|
||||
MvcJsonMvcOptionsSetup.ConfigureMvc(Value, serializerSettings, loggerFactory, ArrayPool<char>.Shared);
|
||||
}
|
||||
|
||||
public MvcOptions Value { get; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue