-
Notifications
You must be signed in to change notification settings - Fork 447
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
Add Config to set output serializer to System.Text.Json #5469
Comments
Thanks @shibayan for opening the issue. Functions v3 uses Regardless of that, this sounds like a fair ask to use Adding @fabiocav if he had any comment on this ask or priority. cc: @brettsam (had a super brief chat on this offline) |
@ankitkumarr Thank you for replying. ASP.NET Core 3.0 (MVC / SignalR) uses |
I actually came here to see if there was an issue covering a move to use STJ when auto-deserializing POCOs as part of an HttpTrigger, etc. but haven't found something encompassing quite that just yet. Would it be fair to write an issue that says we should remove usage of NJ in favor of STJ in v3? Folks that requires NJ for compatibility can then import the package (free of unification struggles, yay!) and continue on, but w/in Functions and as part of things that are auto serialized/deserialized we'd be using STJ. If we don't have an issue like this I'm happy to capture one. I think it would quite heavily impact each first-party extension as well, but they could each get their own similar issue. I'm also happy to help out w/ the effort if acceptable. Or perhaps this better fits as an issue for the Webjobs SDK repo? |
@brandonh-msft the serialization is not the main issue, the binding support is. A large number of apps use This is also the only reason why runtime unification exists, but in the vast majority of cases, this should not present a problem, and you still have the flexibility to reference different versions internally. Do you have a concrete example of a problem you're dealing with because of that behavior? |
I am also currently running into the problem of needing to use a custom JsonConverter that's designed to work with System.Text.Json, but Azure Functions appears to enforce Newtonsoft with no way to override in Startup.Configure |
I'm having an issue with this as well (#5203 (comment)). I believe it is impossible to use
This is annoying because projects shared between an asp.net core project and an azure functions project will have to "live in 2 worlds". Imagine you want to set |
Concerning "Function v3 uses System.Text.Json as input serializer and Newtonsoft.Json as output serializer." I have also observed this to be the case. This is confusing and IMO would have been much more logical if MS had stuck with one or the other. |
I just ran into the same case. Will this get fixed with .NET5 for Azure Functions? |
@stevo-knievo the model with the OOP worker for .NET 5 in functions is a bit different, but you have full control over the stack there. |
@fabiocav thanks for your reply! I'm looking forward to using .NET5 together with Azure Functions. |
I am having trouble with this as well. Internally using is there any way I can work around this? |
Same here, having an object in the model and Sample Object Read from Cosmos via |
This doesn't help people with existing Azure Functions, but the Azure Functions for .net 5 isolated runtime allows you to configure the JSON serialization options now. So for anyone starting new azure functions or have the budget and energy to upgrade existing ones, there's now first-class support for configuring the serializer exactly how you like it. I think System.Text.Json is now the default, but if you want Newtonsoft.Json it looks like there's a way to opt-in to and configure either. I found this example. Program.cs // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Text.Json;
using System.Text.Json.Serialization;
using Azure.Core.Serialization;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace Configuration
{
public class Program
{
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults(workerApplication =>
{
// Use any of the extension methods in WorkerConfigurationExtensions.
})
.Build();
host.Run();
}
}
internal static class WorkerConfigurationExtensions
{
/// <summary>
/// Calling ConfigureFunctionsWorkerDefaults() configures the Functions Worker to use System.Text.Json for all JSON
/// serialization and sets JsonSerializerOptions.PropertyNameCaseInsensitive = true;
/// This method uses DI to modify the JsonSerializerOptions. Call /api/HttpFunction to see the changes.
/// </summary>
public static IFunctionsWorkerApplicationBuilder ConfigureSystemTextJson(this IFunctionsWorkerApplicationBuilder builder)
{
builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
{
jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;
// override the default value
jsonSerializerOptions.PropertyNameCaseInsensitive = false;
});
return builder;
}
/// <summary>
/// The functions worker uses the Azure SDK's ObjectSerializer to abstract away all JSON serialization. This allows you to
/// swap out the default System.Text.Json implementation for the Newtonsoft.Json implementation.
/// To do so, add the Microsoft.Azure.Core.NewtonsoftJson nuget package and then update the WorkerOptions.Serializer property.
/// This method updates the Serializer to use Newtonsoft.Json. Call /api/HttpFunction to see the changes.
/// </summary>
public static IFunctionsWorkerApplicationBuilder UseNewtonsoftJson(this IFunctionsWorkerApplicationBuilder builder)
{
builder.Services.Configure<WorkerOptions>(workerOptions =>
{
var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
});
return builder;
}
}
} |
@tyson-benson Came from Google trying to figure out how to camel case my JSON deserialization for the new .NET 5 isolated process functions. Thank you! |
So for .Net 6 will this functionality be available for all c# functions or only the isolated process functions? |
Is there any news on this ? Now that .NET 6 us supported and the v4 is out |
In my recent adventures with this for .NET 6/Function v4 is that it is still case that you can only configure for STJ if running in an isolated process. Personally, I would like a big hammer that says "AZURE_FUNCTION_PLEASE_CONFIGURE_FOR_STJ_I_AM_AWARE_OF_THE_ISSUES_WITH_JOBJECT_BINDINGS=True". |
'Migrate to System.Text.Json' say all the Microsoft Docs since 2019, yet here we are in March 2023 and Azure Functions doesn't support it. |
Guys, I get it right or I'm missing something ? HttpClient uses STJ and Azure Function HttpTrigger response uses Newtonsoft ? |
We ran into the similar case with Function v4, .net 6, & in-process model. [FunctionName("DataService")]
public static async Task<IActionResult> DataService(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "dataservice/{action:alpha}")] HttpRequest req, string action)
{
IActionResult result = await req.Dispatch(action, DataOptions);
return result;
} Our It works very well in ASP.NET Core environment. Howerver, Azure function throws an exception when a Microsoft.AspNetCore.Mvc.NewtonsoftJson: Property 'JsonResult.SerializerSettings' must be an instance of type 'Newtonsoft.Json.JsonSerializerSettings'. To workaround, we add an extra helper method. private static IActionResult ProcessJsonResult(this IActionResult result)
{
if (result is JsonResult jsonResult)
{
object resultValue = jsonResult.Value;
JsonSerializerOptions options = jsonResult.SerializerSettings as JsonSerializerOptions;
ContentResult contentResult = new()
{
StatusCode = jsonResult.StatusCode,
ContentType = "application/json",
Content = JsonSerializer.Serialize(resultValue, options)
};
result = contentResult;
}
return result;
}
[FunctionName("DataService")]
public static async Task<IActionResult> DataService(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "dataservice/{action:alpha}")] HttpRequest req, string action)
{
IActionResult result = await req.Dispatch(action, DataOptions);
return result.ProcessJsonResult();
} It works... However, we think that the helper method takes more memory(not a stream!) and is not asynchronous. We had migrated from NJ to STJ since STJ takes less memory and is more faster than NJ! |
We recently upgraded to .NET 8, but we have to stick with the in-process model for now. This is blocking us from migrating to |
What problem would the feature you're requesting solve? Please describe.
Solves the problem that input serializer and output serializer are different.
Function v3 uses
System.Text.Json
as input serializer andNewtonsoft.Json
as output serializer. (#5299)When sharing a Domain Model with an ASP.NET Core application, different serializers can cause compatibility issues.
Describe the solution you'd like
I need to change the output serializer to
System.Text.Json
.Describe alternatives you've considered
There is a way to configure all applications to use
Newtonsoft.Json
.However, it does not match the current trend of .NET Core.
Additional context
https://github.com/Azure/azure-functions-host/blob/v3.x/src/WebJobs.Script.WebHost/WebHostServiceCollectionExtensions.cs#L75
The text was updated successfully, but these errors were encountered: