Недавно я обновил свой API до сервера. net core 3.1, используя Swashbuckle 5 с nuget json newtonsoft, который создает схему openapi 3. Затем я использую NSwag для создания API C#. Раньше у меня был сервер. net core 2.2 с функцией swashbuckle 4, который создавал схему api swagger 2.0.
У меня есть общий класс ответа c для всех ответов, содержащий некоторые метаданные об ответе, такие как код состояния и сообщение, а также свойство Payload типа Generi c T, содержащее основную часть ответа.
Когда ответом является код ошибки, я устанавливаю свойство payload равным null. Я изо всех сил пытаюсь найти способ определить свой api, чтобы swashbuckle и NSwag вместе создавали C# api, который позволит свойству полезной нагрузки быть нулевым при десериализации. (swagger 2.0 / swashbuckle 4 работали без проблем).
Как бы я ни старался, свойство Payload всегда получает аннотацию [Newtonsoft.Json.JsonProperty("payload", Required = Newtonsoft.Json.Required.DisallowNull...]
и аннотацию [System.ComponentModel.DataAnnotations.Required]
.
Насколько я понимаю, открытый API 3 теперь позволяет свойствам «$ ref» иметь атрибут «nullable»: true в определении схемы. Если я добавлю это вручную к своему определению после его создания, NSwag правильно удалит атрибут Required в CSharp api и существенно установит для атрибута JsonProperty Required значение «Default» (не обязательно) вместо «DisallowNull».
Однако ничто из того, чем я помечаю свойство полезной нагрузки, не приводит к появлению nullable: true в моем определении схемы json.
Я хочу следующее:
"properties": {
"payload": {
"nullable": true,
"$ref": "#/components/schemas/VisualService.Client.Models.MyResultClass"
},
Я получаю следующее:
"properties": {
"payload": {
"$ref": "#/components/schemas/VisualService.Client.Models.MyResultClass"
},
Что также будет работать, так это установка "nullable" = true на определение самого объекта $ ref, на который имеется ссылка. Я тоже не могу найти способ сделать это.
Я пробовал следующие средства, но безуспешно.
Разметка свойства в классе dto с помощью JsonProperty по-разному:
[JsonProperty(Required = Required.AllowNull)]
public T Payload { get; set; }
[AllowNull]
public T Payload { get; set; }
[MaybeNull]
public T Payload { get; set; }
Попытка сказать Swashbuckle / Newtonsoft использовать мой собственный Json Resolver, как описано в , эта проблема github - не кажется подчиняться
services.AddControllers()
.AddNewtonsoftJson(options =>
{ options.SerializerSettings.ContractResolver = MyCustomResolver();
Я создал свой собственный настраиваемый атрибут и фильтр, чтобы попытаться установить свойство как допускающее значение NULL
[NullableGenericProperty]
public T Payload { get; set; }
[AttributeUsage(AttributeTargets.Property)]
public class NullableGenericPropertyAttribute : Attribute
{
}
public class SwaggerNullablePayloadFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
if (schema?.Properties == null || context?.Type == null)
return;
var nullableGenericProperties = context.Type.GetProperties()
.Where(t =>
t.GetCustomAttribute<NullableGenericPropertyAttribute>()
!= null);
foreach (var excludedProperty in nullableGenericProperties)
{
if (schema.Properties.ContainsKey(excludedProperty.Name.ToLowerInvariant()))
{
var prop = schema.Properties[excludedProperty.Name.ToLowerInvariant()];
prop.Nullable = true;
prop.Required = new HashSet<string>() { "false" };
}
}
}
}
У меня не было большого успеха с этим, в том, что добавление prop.Nullable = true; вызвал удаление атрибута [System.ComponentModel.DataAnnotations.Required]
из c# api. Однако [Newtonsoft.Json.JsonProperty("payload", Required = Newtonsoft.Json.Required.DisallowNull...]
все еще оставался, так что это не сильно помогло. Я добавил prop.Required = new HashSet<string>() { "false" };
в качестве дополнительной попытки, но, похоже, это ничего не дало.
Я мог бы перейти на. net core 2.2 / swashbuckle 4 снова, но 2.2 не имеет долгосрочной поддержки, и я хочу остаться на 3,1, если это вообще возможно. Я также мог бы каждый раз выполнять поиск и замену моего сгенерированного клиента API, но я не хочу, чтобы мне приходилось вручную не забывать делать это каждый раз, когда я регенерирую api, что может быть несколько раз в день в циклах разработки.
У меня есть обходной путь - я перехватываю ответ json и добавляю "nullable" = true
на свой сервер там, где это необходимо, используя соответствие регулярного выражения в строке json ответа ответа перед обслуживая его клиентом. Это действительно взломано, и я бы хотел, чтобы это было сделано, если он существует.
Любая помощь приветствуется!