-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove the Newtonsoft.Json
package and migrate to System.Text.Json
#2125
base: develop
Are you sure you want to change the base?
Changes from all commits
d8c606f
635439b
4d14ebb
646b81c
fe5b2fd
d5c23c0
c7a641c
61247cc
0048df8
c30672f
6215382
dfbc87f
12f1b21
8667047
ac74d64
c6897c9
147271c
b65a6d6
0fda6af
4863b2e
dea5e37
885ee5b
bd2da05
6b67250
f59ca5e
2a213d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -132,7 +132,14 @@ Current `implementation <https://github.com/search?q=repo%3AThreeMammals%2FOcelo | |
.AddApplicationPart(assembly) | ||
.AddControllersAsServices() | ||
.AddAuthorization() | ||
.AddNewtonsoftJson(); | ||
.AddJsonOptions(op => | ||
{ | ||
op.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; | ||
op.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; | ||
op.JsonSerializerOptions.WriteIndented = false; | ||
op.JsonSerializerOptions.PropertyNameCaseInsensitive = true; | ||
op.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); | ||
}); | ||
} | ||
|
||
The method cannot be overridden. It is not virtual, and there is no way to override current behavior by inheritance. | ||
|
@@ -154,74 +161,6 @@ The next section shows you an example of designing custom Ocelot pipeline by cus | |
|
||
.. _di-custom-builder: | ||
|
||
Custom Builder | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand that this sample might contain outdated code, yet it's essential to convert it into something usable. The sample illustrates how to override the default services in the DI feature. We can demonstrate how to revert to the old NewtonSoft services using new package versions. However, the rewriting should be deferred until all C# code is approved. Ultimately, updating the documentation should be the final step in the PR process. |
||
-------------- | ||
|
||
**Goal**: Replace ``Newtonsoft.Json`` services with ``System.Text.Json`` services. | ||
|
||
Problem | ||
^^^^^^^ | ||
|
||
The main `AddOcelot`_ method adds | ||
`Newtonsoft JSON <https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.newtonsoftjsonmvccorebuilderextensions.addnewtonsoftjson>`_ services | ||
by the ``AddNewtonsoftJson`` extension method in default builder (`AddDefaultAspNetServices`_ method). | ||
The ``AddNewtonsoftJson`` method calling was introduced in old .NET and Ocelot releases which was necessary when Microsoft did not launch the ``System.Text.Json`` library, | ||
but now it affects normal use, so we have an intention to solve the problem. | ||
|
||
Modern `JSON services <https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.mvccoremvccorebuilderextensions.addjsonoptions>`_ | ||
out of `the box <https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.mvccoremvccorebuilderextensions>`_ | ||
will help to configure JSON settings by the ``JsonSerializerOptions`` property for JSON formatters during (de)serialization. | ||
|
||
Solution | ||
^^^^^^^^ | ||
|
||
We have the following methods in `ServiceCollectionExtensions`_ class: | ||
|
||
.. code-block:: csharp | ||
|
||
IOcelotBuilder AddOcelotUsingBuilder(this IServiceCollection services, Func<IMvcCoreBuilder, Assembly, IMvcCoreBuilder> customBuilder); | ||
IOcelotBuilder AddOcelotUsingBuilder(this IServiceCollection services, IConfiguration configuration, Func<IMvcCoreBuilder, Assembly, IMvcCoreBuilder> customBuilder); | ||
|
||
These methods with custom builder allow you to use your any desired JSON library for (de)serialization. | ||
But we are going to create custom ``MvcCoreBuilder`` with support of JSON services, such as ``System.Text.Json``. | ||
To do that we need to call ``AddJsonOptions`` extension of the ``MvcCoreMvcCoreBuilderExtensions`` class | ||
(NuGet package: `Microsoft.AspNetCore.Mvc.Core <https://www.nuget.org/packages/Microsoft.AspNetCore.Mvc.Core/>`_) in **Startup.cs**: | ||
|
||
.. code-block:: csharp | ||
|
||
using Microsoft.Extensions.DependencyInjection; | ||
using Ocelot.DependencyInjection; | ||
using System.Reflection; | ||
|
||
public class Startup | ||
{ | ||
public void ConfigureServices(IServiceCollection services) | ||
{ | ||
services | ||
.AddLogging() | ||
.AddMiddlewareAnalysis() | ||
.AddWebEncoders() | ||
// Add your custom builder | ||
.AddOcelotUsingBuilder(MyCustomBuilder); | ||
} | ||
|
||
private static IMvcCoreBuilder MyCustomBuilder(IMvcCoreBuilder builder, Assembly assembly) | ||
{ | ||
return builder | ||
.AddApplicationPart(assembly) | ||
.AddControllersAsServices() | ||
.AddAuthorization() | ||
|
||
// Replace AddNewtonsoftJson() by AddJsonOptions() | ||
.AddJsonOptions(options => | ||
{ | ||
options.JsonSerializerOptions.WriteIndented = true; // use System.Text.Json | ||
}); | ||
} | ||
} | ||
|
||
The sample code provides settings to render JSON as indented text rather than compressed plain JSON text without spaces. | ||
This is just one common use case, and you can add additional services to the builder. | ||
|
||
------------------------------------------------------------------ | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,9 @@ | |
using Ocelot.ServiceDiscovery.Providers; | ||
using Ocelot.WebSockets; | ||
using System.Reflection; | ||
using System.Text.Encodings.Web; | ||
using System.Text.Json.Serialization; | ||
using System.Text.Unicode; | ||
|
||
namespace Ocelot.DependencyInjection; | ||
|
||
|
@@ -108,7 +111,7 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo | |
Services.TryAddSingleton<IHttpHandlerOptionsCreator, HttpHandlerOptionsCreator>(); | ||
Services.TryAddSingleton<IDownstreamAddressesCreator, DownstreamAddressesCreator>(); | ||
Services.TryAddSingleton<IDelegatingHandlerHandlerFactory, DelegatingHandlerHandlerFactory>(); | ||
|
||
Services.TryAddSingleton<IOcelotConfigurationChangeTokenSource, OcelotConfigurationChangeTokenSource>(); | ||
Services.TryAddSingleton<IOptionsMonitor<IInternalConfiguration>, OcelotConfigurationMonitor>(); | ||
|
||
|
@@ -152,7 +155,6 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo | |
/// <summary> | ||
/// Adds default ASP.NET services which are the minimal part of the gateway core. | ||
/// <para> | ||
/// Finally the builder adds Newtonsoft.Json services via the <see cref="NewtonsoftJsonMvcCoreBuilderExtensions.AddNewtonsoftJson(IMvcCoreBuilder)"/> extension-method.<br/> | ||
/// To remove these services, use custom builder in the <see cref="ServiceCollectionExtensions.AddOcelotUsingBuilder(IServiceCollection, Func{IMvcCoreBuilder, Assembly, IMvcCoreBuilder})"/> extension-method. | ||
/// </para> | ||
/// </summary> | ||
|
@@ -163,11 +165,10 @@ public OcelotBuilder(IServiceCollection services, IConfiguration configurationRo | |
/// - <see cref="AnalysisServiceCollectionExtensions.AddMiddlewareAnalysis(IServiceCollection)"/><br/> | ||
/// - <see cref="EncoderServiceCollectionExtensions.AddWebEncoders(IServiceCollection)"/>. | ||
/// <para> | ||
/// Warning! The following <see cref="IMvcCoreBuilder"/> extensions being called:<br/> | ||
/// Warning! The following <see cref="IMvcCoreBuilder"/> extensions being called<br/> | ||
/// - <see cref="MvcCoreMvcCoreBuilderExtensions.AddApplicationPart(IMvcCoreBuilder, Assembly)"/><br/> | ||
/// - <see cref="MvcCoreMvcCoreBuilderExtensions.AddControllersAsServices(IMvcCoreBuilder)"/><br/> | ||
/// - <see cref="MvcCoreMvcCoreBuilderExtensions.AddAuthorization(IMvcCoreBuilder)"/><br/> | ||
/// - <see cref="NewtonsoftJsonMvcCoreBuilderExtensions.AddNewtonsoftJson(IMvcCoreBuilder)"/>, removable. | ||
/// - <see cref="MvcCoreMvcCoreBuilderExtensions.AddAuthorization(IMvcCoreBuilder)"/>. | ||
/// </para> | ||
/// </remarks> | ||
/// <param name="builder">The default builder being returned by <see cref="MvcCoreServiceCollectionExtensions.AddMvcCore(IServiceCollection)"/> extension-method.</param> | ||
|
@@ -184,7 +185,14 @@ protected IMvcCoreBuilder AddDefaultAspNetServices(IMvcCoreBuilder builder, Asse | |
.AddApplicationPart(assembly) | ||
.AddControllersAsServices() | ||
.AddAuthorization() | ||
.AddNewtonsoftJson(); | ||
.AddJsonOptions(op => | ||
{ | ||
op.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; | ||
op.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; | ||
op.JsonSerializerOptions.WriteIndented = false; | ||
op.JsonSerializerOptions.PropertyNameCaseInsensitive = true; | ||
op.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you explain the final goal of these changes to me please? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This setting prevents characters from being escaped when creating JSON. It causes problems in Arabic, Persian, etc. languages. |
||
}); | ||
} | ||
|
||
public IOcelotBuilder AddSingletonDefinedAggregator<T>() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm hesitant to rewrite the documentation until all the code has been verified and approved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not believe we have the authority to change the default settings of the library. Providing recommendations in the documentation to the community should have reasonable goals!
I do not think all Ocelot solutions on the Internet should adhere to these JSON options.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change does not change the library's behavior, so changing this method does not cause any problems.