I set default JsonSerializer to Utf8Json - c#

Using c# 8 and .netcore 3.1.
I've read HERE that Utf8Json library process json serialization and deserialization faster that NewtonsoftJson.
We've recently upgraded our servers code from .netcore 2.2 to 3.1 mostly for performance improvements.
Thus, it is reasonable that we also use the best serialization library.
So my questions are:
In Startup.cs there is this
services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
});
And I want it to use a different library, so I found out that I can use .AddJsonOptions but I cannot figure out how to set default serializer, even after using my google-fu skills.
Since I've been using [JsonProperty("<name>")] everywhere in my code in order to reduce json string size, do I need to format everything for the new serializer or is there a way to make him consider the property attribute ? (attribute is Newtonsoft)
Thanks.

#Ori you can use Utf8json in net core 3.1 projects.
Use
[DataMember(Name = "RoleType")]
public string Role_Type { get; set; }
Instead of
[JsonProperty("<name>")]
To use Utf8json formatters in Asp.Net core you need add the formatters as mentioned below.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
// Add Utf8Json formatters
.AddMvcOptions(option =>
{
option.OutputFormatters.Clear();
option.OutputFormatters.Add(new JsonOutputFormatter (StandardResolver.Default));
option.InputFormatters.Clear();
option.InputFormatters.Add(new JsonInputFormatter ());
});
}
You can also refer below link for the formatters.
https://github.com/neuecc/Utf8Json/blob/master/src/Utf8Json.AspNetCoreMvcFormatter/Formatter.cs
I am using utf8json and its working great for us.

Related

Use Newtonsoft.Json in isolated-process Azure Functions in .Net 6.0

I currently use Azure App Configuration to store all the config data. When i read the data, i would like to use Newtonsoft.Json instead of the default System.Text.Json to correctly transform my data to custom types.
Unfortunately, i cannot find a way to tell the HostBuilder in the Program.cs file to use Newtonsoft.Json instead of the System.Text.Json. All my converters are written using Newtonsoft.Json and i really would like to not migrate them all to System.Text.Json.
As an example:
public Enum SampleEnum
{
[Description("Sample")] SampleAbc
}
public class SampleConfig
{
public SampleEnum ConfigEnumA {get; set;}
}
// configuration is the IConfiguration object from Microsoft.Extensions.Configuration
var sampleConfig = new SampleConfig()
configuration.GetSection("section").bind(sampleConfig);
The Description value Sample is what comes from Azure App Configuration as a string and ideally my current Newtonsoft.Json converters should transform it to SampleAbc enum value when binding the object SampleConfig. This allows me to be type safe in code.
This means that ConfigEnumA should have a value of SampleEnum.SampleAbc instead of Sample
I have already tried using but it did not work although i am working with HTTP Triggers and not a web application
var hostBuilder = new HostBuilder().ConfigureServices(services =>
{
services.AddMvc().AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters = <my-custom-converters>
}
)
});
if there is no way to use Newtonsoft.Json in Azure Function apps that arent Mvc applications, then can someone help with achieving the same behaviour with System.Text.Json?
Thanks for the help.
Cheers.
AFAIK, Services.AddMvcCore().AddJsonOptions(...) is for System.Text.Json whereas builder.services.AddMvcCore().AddNewtonsoftJson(options => can be used for Newtonsoft.json.
If you want to use Newtonsoft, add Microsoft.AspNetCore.Mvc.NewtonsoftJson as a dependency from NuGet which contains AddNewtonsoftJson() extension.
dotnet add package Microsoft.AspNetCore.Mvc.NewtonsoftJson --version 7.0.0
Thanks to #Nate1zn, I found how to use Newtonsoft.Json in Azure Function apps, you can add a startup to your function project as below:
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection
[assembly: FunctionsStartup(typeof(NewtonsoftjsonfunctionApp.functionsample))]
namespace NewtonsoftjsonfunctionApp
public class functionsample : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.services.AddMvcCore().AddNewtonsoftJson(options =>
{
options.SerializerSettings.//json settings
}
}
}

ASP.NET Core 3.1 How can I get the controller to use System.Text.Json to serialize and deserialize

I am converting from .NET CORE 2.2 to 3.1. Is it possible to force the controller to use System.Text.Json to serialize and deserialize any incoming request and response? Basically, when the request comes in I want to use System.Text.Json and when a response goes out I want to use System.Text.Json. If yes, how?
The reason for doing this is that Microsoft is really pushing this library as the replacement for Newtonsoft.Json as being so much safer and faster. But, I cannot seem to find any documentation on Microsoft's pages that reflects this. I find it hard that Microsoft would not update their code to utilize this new library.
UPDATE
I am unable to get System.Text.Json to bind the model by parsing with application/vnd.api+json - the model is NULL. It will only bind if I parse using application/json. This is problematic because the JSON:API specification requires application/vnd.api+json (see here: https://stackoverflow.com/a/61452011/4630376). I tried decorating the controller with [Consumes("application/vnd.api+json")], but that does not work.
How do I get System.Text.Json to bind models using application/vnd.api+json? My initial assumption in asking this question is that .NET Core 3.1 was not using System.Text.Json. Since no one has provided an answer, other than a few comments, I have opted to expand this question.
ChangePassword Model:
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace ABC.Model.Clients
{
public class ChangePassword
{
public ChangePassword() { }
[Required]
[JsonPropertyName("old-password")]
public string OldPassword { get; set; }
[Required]
[JsonPropertyName("new-password")]
public string NewPassword { get; set; }
[Required]
[JsonPropertyName("confirm-password")]
public string ConfirmPassword { get; set; }
}
}
Postman request:
{
"data": {
"attributes": {
"old-password" : "**********",
"new-password" : "**********",
"confirm-password" : "**********"
},
"type": "change-passwords"
}
}
.NET Core 3.0 by default uses System.Text.Json. Check also the official documentation article where this is described.
Regarding the application/vnd.api+json and the JSON:API support in .NET Core 3.0. I am not aware of any support for this in ASP.NET Core. This is a separate standard from plain web API. You cannot just add it as another type you accept and expect it to work.
I found a project on GitHub JSON API .Net Core that provides a framework for building JSON:API compliant web API services. The version for .NET Core 3.0 is at the moment still in Alpha and currently uses Newtonsoft.Json which is not what you want. You can look at the source to see how to handle such requests and maybe build your own solution based on it. Or join the project and help them to make also a System.Text.Json version.
You need to add application/vnd.api+json media type for the SupportedMediaTypes of SystemTextJsonInputFormatter.
services.AddMvc(options =>
{
var formatter = options.InputFormatters.OfType<SystemTextJsonInputFormatter>().FirstOrDefault();
formatter.SupportedMediaTypes.Add("application/vnd.api+json");
});

.Net Core 3.0.100-preview6 - API Json responses are always camelcase, but my classes are not

I have a .net core 3.0 preview 6 MVC application and API.
In the API, I am using a third party class library (that I can't change) which defines the class properties as Pascal cased with the JsonProperty, PropertyName snaked cased eg...
public class Company
{
[JsonProperty(PropertyName = "company_name")]
public string CompanyName { get; set; }
more properties ….
}
The problem is that when I supply these via the api they reach the MVC app as Camel case (the default for .net core 3)... and then can't be Deserialized back the to the class model.
Not matter what I try, the API always produces camel cased JSon, eg. the property above will be called companyName.
I tried,
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver { NamingStrategy = new CamelCaseNamingStrategy { OverrideSpecifiedNames = true } };
options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new DefaultNamingStrategy { OverrideSpecifiedNames = true } };
I've tried NamingStrategy = null on both camel and default ContractResolver. Also tried setting the NamingStrategy to Snake
But nothing changes the outputted Json, it's always camelcased.
I can see the resulting string is camel cased by using ReadAsStringAsync in the MVC app... I when I use JsonConvert.DeserializeObject, the properties are always null, because neither the name or Json PropertyName match the names in the resulting string.
Is this a bug in .net core previews or am missing something else?
Thanks Mustafa, your suggested duplicate is kinda the same issue with kinda the same solutions that I've already tried i.e. changing the setting of the ContractResolver / NamingStrategy to different values.... however, My issue is that none of the suggested solutions appear to have any effect on the API response it always comes back as camelCased.
Interestingly, when I change the NamingStrategy to say Snake, Swagger shows the schema as set (i.e. snake) but the actual output is still camelCased!!!
Also, I have no control over the base classes so I can't change the names / json properties of the classes I'm attempting to transmit.
Microsoft.AspNetCore.Mvc.NewtonsoftJson
Doesn't come up default.
Try to install this nuget package manually to your service project. That worked for me.
Try this and remove all JsonProperty attributes.
From now if you don't specify any JsonPropertyy it will act like this CompanyName like company_name or ProPertyName1 like pro_perty_name1. In this examples will explain the idea of the property name.
And be sure add this configuration to bottom of the ConfigureServices method, it may overwritten by another things i dont know.
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new DefaultContractResolver { NamingStrategy = new SnakeCaseNamingStrategy() };
});
Not really sure where the issue was but had a feeling it was something to do with the mix of Newtonsoft.Json, Json.Net, Swagger and the fact that I was using the Microsoft.AspNet.WebApi.Client to get the HttpContent.ReadAsAsync….all having different Json's
So, I decided to start again with a real simple app and api using the new System.Text.Json included in .Net Core preview (and none of the other libraries). Also not using the HttpContent.ReadAsAsync but instead reading the response as a string and then deserializing with the new library (System.Text.Json)
Doing this I had exactly the same issue …. neither the property name or Json PropertyName match the names in the api returned string i.e class property name = "CompanyName" and Json PropertyName = "company_name" and the api supplied json name = "companyName". So the value isn't set when Deserializing.
However, in the new System.Text.Json options I'm able to specify PropertyNameCaseInsensitive = true, which fixes my problem, now companyName does equal CompanyName and the class model values are set correctly when Deserializing.
So my api call methods end up looking like this...
using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, string.Format("Companies?aCompanyName={0}", aCompanyName));
using HttpResponseMessage response = await Client.SendAsync(request);
string content = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode == false)
{
throw new ApiException
{
StatusCode = (int)response.StatusCode,
Content = content
};
}
_JsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
return JsonSerializer.Deserialize<IEnumerable<Company>> (content, _JsonOptions);
I did attempt to set the JsonSerializerOptions globally in the startup class but this didn't work.
I've transferred this approach to all my http calls in my app, removed all references to Newtonsoft and it all works.
I came across this issue when converting my api from .netcore 2.2 to .netcore 3.
My api was returning responses converted to camelCase even though my models were PascalCase.
In startup.cs:
.netcore 2:
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
.netcore 3:
// keeps the casing of models when serializing to json (default is converting to camelCase)
services.AddMvc()
.AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
This means you don't need to import newtonsoft.json.

How to prevent json results in MVC .net core to lowercase first letter of model properties [duplicate]

I've just swapped our project from ASP .Net Core 1.0.0-rc2-final to 1.0.0. Our website and client have stopped working because of the capitalization of JSON properties. For example, this line of JavaScript now fails
for (var i = 0; i < collection.Items.length; i++){
because the controller now calls the array "items" instead of "Items". I have made no changes beyond installing the updated packages and editing the project.json file. I have not changed the C# model files which still capitalize their properties.
Why have the ASP.Net Core controllers started returning JSON with lower-cased properties? How do I go back to them honoring the case of the property names from the model?
MVC now serializes JSON with camel case names by default
Use this code to avoid camel case names by default
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
Source:
https://github.com/aspnet/Announcements/issues/194
In case you found this from Google and looking for a solution for Core 3.
Core 3 uses System.Text.Json, which by default does not preserve the case. As mentioned with this GitHub issue, setting the PropertyNamingPolicy to null will fix the problem.
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllers()
.AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);
and if you don't want to change the global settings, for one action only it's like this:
return Json(obj, new JsonSerializerOptions { PropertyNamingPolicy = null });
You can change the behavior like this:
services
.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
See the announcement here: https://github.com/aspnet/Announcements/issues/194
For those who migrated to Core 3.1 and have Core MVC project can use following setup code in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllersWithViews().AddJsonOptions(opts => opts.JsonSerializerOptions.PropertyNamingPolicy = null);
...
}
This will fix it in dotnet core 3 webapi, so that it doesn't change your property names at all, and you return to your client exactly what you intended to.
In Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
services.AddHttpClient();
}
For someone who does not want to set it globally, it is possible to use ContractResolver also to return as Json result:
public IActionResult MyMethod()
{
var obj = new {myValue = 1};
return Json(obj, new JsonSerializerSettings {ContractResolver = new DefaultContractResolver()});
}
For some one who is using ASP.net WEB API ( rather than ASP.NET Core).
Add this line in your WebApiConfig.
//Comment this jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
jsonFormatter.SerializerSettings.ContractResolver = new DefaultContractResolver();
Adding this as an answer here because this comes up first in google search for web api as well.
For ASP MVC Core 6 Web API , Add below code into Program.cs file will make sure JSON propreties name follow C# model properties name in right casing. No 3rd party package require
using Microsoft.AspNetCore.Mvc;
builder.Services.Configure<JsonOptions>(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
For Core 2.x versions, using this code you can avoid camel case names by default. You need to add following code inside the ConfigureServices method of Startup.cs file.
services.AddMvc()
.AddJsonOptions(o =>
{
if (o.SerializerSettings.ContractResolver != null)
{
var castedResolver = o.SerializerSettings.ContractResolver
as DefaultContractResolver;
castedResolver.NamingStrategy = null;
}
});
Recently had this issue with .Net6
The solution turned out to be that I needed to install
Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.0.x (Note, use 7.x for .Net 7)
Found this out from Mason's post:
Microsoft.AspNetCore.Mvc.NewtonsoftJson 6.0.2 is not compatible with net5.0
Install
Microsoft.AspNetCore.Mvc.NewtonsoftJson
For .net 6 you should select this version: 6.0.13
and then go to Program.cs and configure it like this
builder.Services
.AddControllersWithViews()
.AddNewtonsoftJson(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());

XmlSerializerInputFormatter deprecated, what's the replacement? [duplicate]

I am using the following to accept XML serialized in my Core API App.
services.AddMvc(options =>
{
// allow xml format for input
options.InputFormatters.Add(new XmlSerializerInputFormatter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
After updating to ASP.NET Core 2.1 I receive the following warning:
'XmlSerializerInputFormatter.XmlSerializerInputFormatter()' is obsolete: 'This constructor is obsolete and will be removed in a future version.'
What is the new way to handle this?
According to the source code, there's a constructor that has not been marked as Obsolete:
public XmlSerializerInputFormatter(MvcOptions options)
This constructor takes an instance of MvcOptions, so you can pass through your existing options argument:
services.AddMvc(options =>
{
// allow xml format for input
options.InputFormatters.Add(new XmlSerializerInputFormatter(options));
}) ...
As of ASP.NET Core 3.0, this constructor is the only one available. Those that were marked obsolete have now been removed.
With .NET Core 2.2 or later XmlSerializerInputFormatter should be marked as deprecated.
Instead a of explicitly defining XML serializers as we did before, in the .NET Core 2.2 we can add them simply by calling AddXmlSerializerFormatters() method which will do the job now. Read here why it has been deprecated
Here is how you can do it.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(config =>
{
config.RespectBrowserAcceptHeader = true;
config.ReturnHttpNotAcceptable = true;
config.OutputFormatters.Add(new CsvOutputFormatter());
}).AddXmlSerializerFormatters().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

Categories