Пользовательский конвертер Newtonsoft не вызывается в минимальном API .NET 8C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Пользовательский конвертер Newtonsoft не вызывается в минимальном API .NET 8

Сообщение Anonymous »

У нас есть API проверки версий, который мы обновляем с .NET Core 3.1 до минимального API .NET 8. Он должен быть обратно совместим, но мы столкнулись с проблемой.
Начиная с .NET 6, сериализация JSON по умолчанию для System.Version изменилась. Мы написали конвертер, который наследует от Newtonsoft.Json.JsonConverter.
Я пытался добавить конвертер в сборщик приложений, но при вызове конечной точки он вызывает сериализацию по умолчанию вместо пользовательской. кода, и у меня недостаточно опыта в этой области, чтобы понять, чего мне не хватает.
Как мне это настроить, чтобы получить пользовательскую сериализацию?
Ожидаемый результат:
{"version":{"major":9,"minor":16,"build":6,"revision":-1,"majorRevision":-1,"minorRevision":-1
Фактический результат:
{"version":"9.16.2"
VersionConverter
public class VersionConverter : JsonConverter
{
public override bool CanRead => true;
public override bool CanWrite => true;

public override Version ReadJson(JsonReader reader, Type objectType, Version existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.StartObject)
{
int major = 0, minor = 0, build = -1, revision = -1;

while (reader.Read() && reader.TokenType != JsonToken.EndObject)
{
if (reader.TokenType == JsonToken.PropertyName)
{
string propertyName = reader.Value.ToString();
reader.Read();

switch (propertyName)
{
case "major":
major = Convert.ToInt32(reader.Value);
break;
case "minor":
minor = Convert.ToInt32(reader.Value);
break;
case "build":
build = Convert.ToInt32(reader.Value);
break;
case "revision":
revision = Convert.ToInt32(reader.Value);
break;
}
}
}

return new Version(major, minor, build, revision);
}

throw new JsonSerializationException("Unexpected token when deserializing Version");
}

public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer)
{
writer.WriteStartObject();
writer.WritePropertyName("major");
writer.WriteValue(value.Major);
writer.WritePropertyName("minor");
writer.WriteValue(value.Minor);
writer.WritePropertyName("build");
writer.WriteValue(value.Build);
writer.WritePropertyName("revision");
writer.WriteValue(value.Revision);
writer.WritePropertyName("majorRevision");
writer.WriteValue(value.MajorRevision);
writer.WritePropertyName("minorRevision");
writer.WriteValue(value.MinorRevision);
writer.WriteEndObject();
}
}

Ответ проверки версии
public class VersionCheckResponse
{
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; set; }
}

Program.cs (упрощенный)
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllers().AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new VersionConverter());
});

builder.Services.AddApiVersioning(options =>
{
options.ReportApiVersions = true;
options.DefaultApiVersion = new ApiVersion(1, 0);
options.AssumeDefaultVersionWhenUnspecified = true;
options.ApiVersionReader = new HeaderApiVersionReader(HeaderNames.ApiVersion);
});
builder.Services.AddScoped();
builder.Services.AddControllers();

// Configure routing options for case-insensitive endpoints
builder.Services.Configure(options =>
{
options.LowercaseUrls = true;
options.LowercaseQueryStrings = true;
});

WebApplication app = builder.Build();

app.MapGet("/version", ([FromServices] IVersionManager versionManager, [FromQuery] string productName, [FromQuery] Version productVersion) =>
{
ValidationResult result = versionManager.CheckVersion(productName, productVersion);
if (result.IsValid)
{
return Results.Ok(new ApiResponse(result.Value));
}

return Results.BadRequest(new ApiResponse(result.ValidationMessage, result.ValidationErrors));
});

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.MapHealthChecks("/health");
app.Run();

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: после того, как вопрос был закрыт как дубликат, я сослался на другой вопрос и попытался сделать то же самое с System.Text.Json. Я также изменил Program.cs. Я получаю тот же результат.
VersionJsonConverter
public class VersionJsonConverter : System.Text.Json.Serialization.JsonConverter
{
public override Version Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
// Handle the case where the input is the string version like "9.16.6"
if (reader.TokenType == JsonTokenType.String)
{
string versionString = reader.GetString();
return Version.Parse(versionString);
}

// Handle the case for the old format
if (reader.TokenType == JsonTokenType.StartObject)
{
JsonDocument doc = JsonDocument.ParseValue(ref reader);
JsonElement root = doc.RootElement;

int major = root.GetProperty("major").GetInt32();
int minor = root.GetProperty("minor").GetInt32();
int build = root.GetProperty("build").GetInt32();
int revision = root.TryGetProperty("revision", out JsonElement rev) ? rev.GetInt32() : -1;
int majorRevision = root.TryGetProperty("majorRevision", out JsonElement majRev) ? majRev.GetInt32() : -1;
int minorRevision = root.TryGetProperty("minorRevision", out JsonElement minRev) ? minRev.GetInt32() : -1;

return new Version(major, minor, build, revision);
}

throw new JsonException("Invalid format for Version");
}

public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options)
{
// If you want to serialize in the old format with major, minor, build, revision etc.
writer.WriteStartObject();
writer.WriteNumber("major", value.Major);
writer.WriteNumber("minor", value.Minor);
writer.WriteNumber("build", value.Build);
writer.WriteNumber("revision", value.Revision); // Can be -1 if not specified
writer.WriteNumber("majorRevision", -1); // For compatibility, you can set these to -1
writer.WriteNumber("minorRevision", -1);
writer.WriteEndObject();
}
}


Модификации Program.cs
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new VersionJsonConverter());
});


Подробнее здесь: https://stackoverflow.com/questions/792 ... inimal-api
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»