JSON Serialization
WARNING
At this point WolverineFx.Http only supports System.Text.Json
as the default for the HTTP endpoints, with the JSON settings coming from the application's Minimal API configuration.
TIP
You can tell Wolverine to ignore all return values as the request body by decorating either the endpoint method or the whole endpoint class with [EmptyResponse]
As explained up above, the "request" type to a Wolverine endpoint is the first argument that is:
- Concrete
- Not one of the value types that Wolverine considers for route or query string values
- Not marked with
[FromServices]
from ASP.Net Core
If a parameter like this exists, that will be the request type, and will come at runtime from deserializing the HTTP request body as JSON.
Likewise, any resource type besides strings will be written to the HTTP response body as serialized JSON.
In this sample endpoint, both the request and resource types are dealt with by JSON serialization. Here's the test from the actual Wolverine codebase:
[Fact]
public async Task post_json_happy_path()
{
// This test is using Alba to run an end to end HTTP request
// and interrogate the results
var response = await Scenario(x =>
{
x.Post.Json(new Question { One = 3, Two = 4 }).ToUrl("/question");
x.WithRequestHeader("accept", "application/json");
});
var result = await response.ReadAsJsonAsync<ArithmeticResults>();
result.Product.ShouldBe(12);
result.Sum.ShouldBe(7);
}
Configuring System.Text.Json
Wolverine depends on the value of the IOptions<Microsoft.AspNetCore.Http.Json.JsonOptions>
value registered in your application container for System.Text.Json configuration.
But, because there are multiple JsonOption
types in the AspNetCore world and it's way too easy to pick the wrong one and get confused and angry about why your configuration isn't impacting Wolverine, there's this extension method helper that will do the right thing behind the scenes:
var builder = WebApplication.CreateBuilder();
builder.Host.UseWolverine();
builder.Services.ConfigureSystemTextJsonForWolverineOrMinimalApi(o =>
{
// Do whatever you want here to customize the JSON
// serialization
o.SerializerOptions.WriteIndented = true;
});
var app = builder.Build();
app.MapWolverineEndpoints();
return await app.RunOaktonCommands(args);
Using Newtonsoft.Json
TIP
Newtonsoft.Json is still much more battle hardened than System.Text.Json, and you may need to drop back to Newtonsoft.Json for various scenarios. This feature was added specifically at the request of F# developers.
To opt into using Newtonsoft.Json for the JSON serialization of HTTP endpoints, you have this option within the call to the MapWolverineEndpoints()
configuration:
var builder = WebApplication.CreateBuilder([]);
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddMarten(Servers.PostgresConnectionString)
.IntegrateWithWolverine();
builder.Host.UseWolverine(opts =>
{
opts.Discovery.IncludeAssembly(GetType().Assembly);
});
builder.Services.AddWolverineHttp();
await using var host = await AlbaHost.For(builder, app =>
{
app.MapWolverineEndpoints(opts =>
{
// Opt into using Newtonsoft.Json for JSON serialization just with Wolverine.HTTP routes
// Configuring the JSON serialization is optional
opts.UseNewtonsoftJsonForSerialization(settings => settings.TypeNameHandling = TypeNameHandling.All);
});
});