I'm currently working on an ASP.NET Core 8 Web API. I have already configured the application to serialize and deserialize JSON messages to and from controller endpoints with JsonNamingPolicy.CamelCase
using .AddControllers(...).AddJsonOptions()
.
I use a simple text file sink with messages, and Serilog configuration is the standard used for a Web API.
When I try to log the object after a successful deserialization, just inside the controller methods, the Serilog destructurer serializes the object to JSON in PascalCase, as in the original case of the object class model.
How do I apply JsonNamingPolicy.CamelCase
to Serilog configuration/destructurer?
Example of json sent to my API:
{
"textField": "value", "uselessField": "value2"
}
My API deserializes to input model object:
public class Input
{
public string TextField { get; set; }
}
I log the input object after deserialization with this line
_logger.LogDebug("API RECEIVED {@InputModel}"}, input);
The log message part is written as:
API RECEIVED {"TextProp":"value"}
but I need camelCase format:
API RECEIVED {"textProp":"value"}
Is there a possible solution?
The JSON library used is System.Text.Json
.
I'm currently working on an ASP.NET Core 8 Web API. I have already configured the application to serialize and deserialize JSON messages to and from controller endpoints with JsonNamingPolicy.CamelCase
using .AddControllers(...).AddJsonOptions()
.
I use a simple text file sink with messages, and Serilog configuration is the standard used for a Web API.
When I try to log the object after a successful deserialization, just inside the controller methods, the Serilog destructurer serializes the object to JSON in PascalCase, as in the original case of the object class model.
How do I apply JsonNamingPolicy.CamelCase
to Serilog configuration/destructurer?
Example of json sent to my API:
{
"textField": "value", "uselessField": "value2"
}
My API deserializes to input model object:
public class Input
{
public string TextField { get; set; }
}
I log the input object after deserialization with this line
_logger.LogDebug("API RECEIVED {@InputModel}"}, input);
The log message part is written as:
API RECEIVED {"TextProp":"value"}
but I need camelCase format:
API RECEIVED {"textProp":"value"}
Is there a possible solution?
The JSON library used is System.Text.Json
.
- 1 Why do you care? – mjwills Commented Mar 18 at 23:32
- it's to check if deserialization missed some fields in case the subcontractor made some errors in their calls composition. We have tons of fields in the models but if all properties are deserialized with the wrong case i can't compare in a fast way the HTTP body and the deserialized object. This api is being integrated and called by tons of different clients and i have to check often, despite out swagger is 1:1 on out models. – albe Commented Mar 18 at 23:39
1 Answer
Reset to default 2You can create a custom CamelCase policy to implement this feature.
Test Code
[HttpPost]
public IActionResult Post([FromBody] InputModel input)
{
_logger.LogDebug("API RECEIVED {@InputModel}", input);
return Ok();
}
Test Result
Here is the details.
CamelCaseDestructuringPolicy.cs
using Serilog.Core;
using Serilog.Events;
using System.Text.Json;
namespace _79518749
{
public class CamelCaseDestructuringPolicy : IDestructuringPolicy
{
public bool TryDestructure(
object value,
ILogEventPropertyValueFactory propertyValueFactory,
out LogEventPropertyValue? result)
{
var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false
};
try
{
var json = JsonSerializer.Serialize(value, options);
var dict = JsonSerializer.Deserialize<Dictionary<string, object>>(json, options);
var properties = dict.Select(kv =>
new LogEventProperty(kv.Key, new ScalarValue(kv.Value)));
result = new StructureValue(properties);
return true;
}
catch
{
result = null;
return false;
}
}
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.Destructure.With<CamelCaseDestructuringPolicy>()
.WriteTo.Console()
.CreateLogger();
builder.Host.UseSerilog();
builder.Services.AddControllers()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
...