Reputation: 8402
I have a set of Azure Functions v3 running on .net core 3.1.
I have a custom configuration of JsonSerializerOptions
that I want to be used automatically by my functions when de/serializing data.
Question
How can I set up my Azure Functions so that they can use my default System.Text.Json.JsonSerializerOptions
instance?
Update 1
Following the suggestion from @sellotape, I found out the following documentation regarding the JsonResult
class:
The problem is that my JsonResult
instance does not have this property of type object ; it is only accepting a JsonSerializerSettings
instance.
Update 2
I still get the following error and I am not sure where Newtonsoft is coming from:
Microsoft.AspNetCore.Mvc.NewtonsoftJson: Property 'JsonResult.SerializerSettings' must be an instance of type 'Newtonsoft.Json.JsonSerializerSettings'.
Upvotes: 15
Views: 15524
Reputation: 721
It's not a perfect solution for those with existing Azure Function apps, 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. It's unfortunate that enums have been second class citizens until just now, but better late than never.
Program.cs
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace MyFunctionApp
{
public class Program
{
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.ConfigureServices(services =>
{
services.Configure<JsonSerializerOptions>(options =>
{
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
options.Converters.Add(new JsonStringEnumConverter());
});
})
.Build();
host.Run();
}
}
}
If you want to pick System.Text.Json or Newtonsoft.Json there you could configure either one like seen in this example
// 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;
}
}
}
Upvotes: 19
Reputation: 8402
Turns out I missed a step when upgrading my Azure Functions from v2 to v3. To make it work, I had to add the Microsoft.AspNetCore.App
framework to my csproj
. Otherwise, my project kept referencing JsonResult
from Microsoft.Aspnet.Mvc.Core
v2.X.X which does not support System.Text.Json
.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<!-- ADD THESE LINES -->
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
</Project>
Then, I was able to specify my own JsonSerializerOptions
instance like this:
return new JsonResult(<ContractClass>, NSJsonSerializerOptions.Default)
{
StatusCode = StatusCodes.Status200OK
};
where NSJsonSerializerOptions.Default
is a static instance of JsonSerializerOptions
.
Upvotes: 4