I wrote a string custom System.Text.Json converter
public class TranslatableJsonConverter : JsonConverter<string>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public TranslatableJsonConverter(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options)
{
var request = _httpContextAccessor.HttpContext?.Request;
if (request is null)
{
writer.WriteStringValue(value);
return;
}
var acceptLanguage = request.GetUserLanguage();
writer.WriteStringValue($"KPI_FAMILY_{value}".Translate(acceptLanguage));
}
}
Here, I injected the IHttpContextAccessor because I have to retrieve an header field to process a string property of a record dto.
Then I registered the custom converter in the following way:
public class ConfigureJsonOptions : IConfigureOptions<JsonOptions>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ConfigureJsonOptions(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void Configure(JsonOptions options)
{
options.JsonSerializerOptions.Converters.Add(new TranslatableJsonConverter(_httpContextAccessor));
}
}
// Startup.cs
services.AddHttpContextAccessor();
services.ConfigureOptions<ConfigureJsonOptions>();
So, I decorated the property that I'd like to process:
public record DriverBehaviourFamilyCountersDto
{
[JsonConverter(typeof(TranslatableJsonConverter))]
public string Name { get; set; }
public IEnumerable<BehaviourCounterDto> Behaviours { get; set; }
}
The problem is that I get the following exception, when serialization happens
System.InvalidOperationException: The converter specified on 'Video.Analytics.DriverBehavior.Coaching.BFF.Api.Dto.Output.DriverBehaviourFamilyCountersDto.Name' does not derive from JsonConverter or have a public parameterless constructor.\r\n at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_SerializationConverterOnAttributeInvalid(Type classType, MemberInfo memberInfo)\r\n at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetConverterFromAttribute(JsonConverterAttribute converterAttribute, Type typeToConvert, MemberInfo memberInfo, JsonSerializerOptions options)\r\n at System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.GetCustomConverterForMember(Type typeToConvert, MemberInfo memberInfo, JsonSerializerOptions options)\r\n at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo
1.CreateProperty(Type typeToConvert, MemberInfo memberInfo, JsonSerializerOptions options, Boolean shouldCheckForRequiredKeyword)\r\n at System.Text.Json.Serialization.Metadata.ReflectionJsonTypeInfo1.LateAddProperties()\r\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo.InitializePropertyCache()\r\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo.Configure()\r\n
at System.Text.Json.Serialization.Metadata.JsonTypeInfo.g__ConfigureLocked|143_0()\r\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo.EnsureConfigured()\r\n at System.Text.Json.JsonSerializerOptions.GetTypeInfoInternal(Type type, Boolean ensureConfigured, Boolean resolveIfMutable)\r\n at System.Text.Json.Serialization.Metadata.JsonTypeInfo.get_ElementTypeInfo()\r\n at System.Text.Json.Serialization.JsonCollectionConverter2.OnTryWrite(Utf8JsonWriter writer, TCollection value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.Serialization.JsonConverter1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.Serialization.Metadata.JsonPropertyInfo1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)\r\n at System.Text.Json.Serialization.Converters.ObjectDefaultConverter1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.Serialization.JsonConverter1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.Serialization.JsonConverter1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.Serialization.JsonConverter`1.WriteCoreAsObject(Utf8JsonWriter writer, Object value, JsonSerializerOptions options, WriteStack& state)\r\n at System.Text.Json.JsonSerializer.WriteCore[TValue](Utf8JsonWriter writer, TValue& value, JsonTypeInfo jsonTypeInfo, WriteStack& state)\r\n at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)\r\n at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)\r\n at System.Text.Json.JsonSerializer.WriteStreamAsync[TValue](Stream utf8Json, TValue value, JsonTypeInfo jsonTypeInfo, CancellationToken cancellationToken)\r\n at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonOutputFormatter.WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|30_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)\r\n at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n at Serilog.AspNetCore.RequestLoggingMiddleware.Invoke(HttpContext httpContext)\r\n at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)"
Could you help me please?