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