当前位置: 首页 > 知识库问答 >
问题:

使用斜扣5。x在泛型T参数引用属性上指定nullable=true

颜修明
2023-03-14

我最近将API升级到了。net core 3.1服务器使用Swashback 5和newtonsoft json nuget,后者生成openapi 3模式。然后,我使用NSwag生成一个C#API。以前我有一个。net core 2.2服务器和Swashbucklk 4,生成swagger 2.0 api模式。

我有一个用于所有响应的通用响应类,其中包含一些关于响应的元数据,如状态代码和消息,以及一个包含响应内容的通用类型T的有效负载属性。

当响应是错误代码时,我将有效负载属性设置为null。我正在努力寻找一种方法来定义我的api,以便swashuckle和NSwag组合生成一个C#api,该api将允许有效负载属性在反序列化时为空。(swagger 2.0/swashuckle 4没有问题)。

尽我所能,Payload属性总是获取注释[Newtonsoft.Json.JsonProperty(“Payload”,Required=Newtonsoft.Json.Required.DisallowNull…] 和<代码>[系统.组件模型.数据注释.必需]注释。

据我所知,开放式API 3现在允许“$ref”属性在模式定义中具有“nullable”:true属性。如果在创建定义后手动将其添加到定义中,NSwag会正确删除CSharp api中的必需属性,并将JsonProperty必需属性设置为“Default”(非必需)而不是“DisallowNull”
然而,我标记payload属性所用的任何内容都不会导致null:true出现在我的模式json定义中。

我想要的是:

"properties": {
          "payload": {
            "nullable": true, 
            "$ref": "#/components/schemas/VisualService.Client.Models.MyResultClass"
          },

我得到的是:

"properties": {
          "payload": {
            "$ref": "#/components/schemas/VisualService.Client.Models.MyResultClass"
          },

还可以在引用的$ref对象本身的定义上设置“nullable”=true。我也找不到这样做的方法。

我尝试了以下补救措施,但没有成功。

>

[JsonProperty(Required = Required.AllowNull)]
public T Payload { get; set; }

[AllowNull]
public T Payload { get; set; }

[MaybeNull]
public T Payload { get; set; }

试图告诉SwashBuckl/Newtonsoft使用我的自定义Json解析器(如本期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" };
                }
            }
        }
    }

我在这件事上取得了小小的成功,那就是增加了道具。Nullable=真;导致从c#api中删除属性[System.ComponentModel.DataAnnotations.Required]。但是,Newtonsoft.Json.JsonProperty(“payload”,Required=Newtonsoft.Json.Required.DisallowNull…] 仍然保留,所以没有多大帮助。我添加了属性。必需=新哈希集

我可以降级到。网芯2.2/斜扣4再次出现,但2.2已失去长期支撑,如果可能的话,我希望保持在3.1。我也可以每次在生成的API客户端上进行查找和替换,但我不想每次重新生成API时都手动记住这样做,因为在开发周期中,每天可能会有几次。

我有一个hacky解决方法——在将其提供给客户端之前,我通过在响应body json字符串上使用正则表达式匹配来拦截json响应并在需要的地方在我的服务器上添加"nullable"=true。不过,它真的很hacky,如果它存在,我希望有一种本地方法来做到这一点。

任何和所有的帮助感谢!

共有1个答案

仲俊豪
2023-03-14

有一个设置可以实现这一点:

UseAllOfToExtendReferenceSchemas 

它将模式更改为该模式,nswag可以使用该模式允许$ref属性为null。

  "payload": {
    "required": [
      "false"
    ],
    "allOf": [
      {
        "$ref": "#/components/schemas/MyResultClass"
      }
    ],
    "nullable": true
  },

像这样使用它:

        _ = services.AddSwaggerGen(setup =>
        {
            setup.SwaggerDoc("v1", new OpenApiInfo { Title = AppConst.SwaggerTitle, Version = "v1" });

            setup.UseAllOfToExtendReferenceSchemas();
            ...
 类似资料:
  • 我正在尝试创建一个对通用数字类型的特征抽象。指定我希望特征需要(即

  • 我使用的是Azure.data.tables nuget包的12.0.0-beta.6。当我尝试调用TableClient.GetQueryAsync时,它会给出错误: “类型”T“必须是引用类型,才能将其用作泛型类型或方法”TableClient.GetEntityAsync(string,string,IEnumerable,CancellationToken)“中的参数”T“。” 我看不出我

  • 我只想从使用Log4j(v2.8.2)的Java移植以下代码: 问题在于newBuilder()方法,该方法在log4j中定义为某种递归泛型: Java代码会自动推断泛型参数,而Kotlin的情况并非如此。在Kotlin中调用此方法有什么解决方案吗? 我在Kotlin尝试的代码: 它有以下错误: 错误:(90,48)静态编程语言:类型推断失败:没有足够的信息来推断参数B的乐趣! 当代码在粘贴时自动

  • 我正在创建一个接口和链表的实现,如Java1.8: 接口没有编译器问题,但给出了错误其中我有

  • 问题内容: 的Java,C#和打字稿(亦称语言的太阳/ Hejlsberg家庭)使用,,等来表示泛型类型参数。从表面上看,这是因为代表“ Type”,然后跟随字母。 在另一方面,Scala的使用,,等,和OCaml中和Haskell的使用,和。 这些约定从何而来?难道是因为函数式语言更接近数学证明,在那里,和被用约定? 问题答案: 在标准Java SE API中,设计人员通常选择一个与类型参数的含

  • 问题内容: 为通用Java方法显式提供类型参数的语法是什么? 问题答案: 以下 不是 语法 似乎类型参数 必须 在圆点后,如