You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NSwagStudio生成C#客户端时重复创建类的问题求助

如何让NSwagStudio为重复的attributes结构只生成一个C#类?

我用NSwagStudio从OpenAPI文档生成C#客户端,功能正常,但有个问题:OpenAPI里Person、Address等对象里都有完全一样的attributes结构,NSwag却生成了上百个重复类(比如Attributes、Attributes2、Attributes372),总数超700个。

相关OpenAPI示例

{
  "components": {
    "schemas": {
      "Person": {
        "type": "object",
        "properties": {
          "Id": { "type": "string" },
          "Name": { "type": "string" },
          "First Name": { "type": "string" },
          "Lastname": { "type": "string" },
          "attributes": {
            "type": "object",
            "properties": {
              "type": { "type": "string" },
              "url": { "type": "string" }
            }
          }
        },
        "description": "Account Object"
      },
      "Address": {
        "type": "object",
        "properties": {
          "Id": { "type": "string" },
          "Street": { "type": "string" },
          "Post Code": { "type": "string" },
          "City": { "type": "string" },
          "Country": { "type": "string" },
          "attributes": {
            "type": "object",
            "properties": {
              "type": { "type": "string" },
              "url": { "type": "string" }
            }
          }
        },
        "description": "Address Object"
      }
    }
  }
}

生成的重复C#类示例

public partial class Attributes{
    [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Type { get; set; }

    [Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Url { get; set; }

    private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();

    [Newtonsoft.Json.JsonExtensionData]
    public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
    {
        get { return _additionalProperties; }
        set { _additionalProperties = value; }
    }

    public string ToJson()
    {
        return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings());
    }
    public static Attributes FromJson(string data)
    {
        return Newtonsoft.Json.JsonConvert.DeserializeObject<Attributes2>(data, new Newtonsoft.Json.JsonSerializerSettings());
    }
}

public partial class Attributes2{
    [Newtonsoft.Json.JsonProperty("type", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Type { get; set; }

    [Newtonsoft.Json.JsonProperty("url", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Url { get; set; }

    private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();

    [Newtonsoft.Json.JsonExtensionData]
    public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
    {
        get { return _additionalProperties; }
        set { _additionalProperties = value; }
    }

    public string ToJson()
    {
        return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings());
    }
    public static Attributes2 FromJson(string data)
    {
        return Newtonsoft.Json.JsonConvert.DeserializeObject<Attributes2>(data, new Newtonsoft.Json.JsonSerializerSettings());
    }
}

路径部分的$ref引用

{
  "/Person": {
    "description": "",
    "get": {
      "responses": {
        "200": {
          "description": "Status Code 200",
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/Person" }
            }
          }
        }
      }
    }
  }
}

生成的Person类示例

public partial class Person{
    [Newtonsoft.Json.JsonProperty("Id", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Id { get; set; }

    [Newtonsoft.Json.JsonProperty("Name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string Name{ get; set; }

    [Newtonsoft.Json.JsonProperty("LastName", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string LastName { get; set; }

    [Newtonsoft.Json.JsonProperty("FirstName", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public string FirstName { get; set; }

    [Newtonsoft.Json.JsonProperty("attributes", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public Attributes372 Attributes { get; set; }

    private System.Collections.Generic.IDictionary<string, object> _additionalProperties = new System.Collections.Generic.Dictionary<string, object>();

    [Newtonsoft.Json.JsonExtensionData]
    public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
    {
        get { return _additionalProperties; }
        set { _additionalProperties = value; }
    }
}

解决方案

可以实现只生成一个Attributes类,有两种可行方式:

1. 修改OpenAPI文档(推荐)

把重复的attributes结构提取成独立的Schema,用$ref引用它,这样NSwag会识别为同一个类型。

修改后的OpenAPI示例:

{
  "components": {
    "schemas": {
      "Attributes": {
        "type": "object",
        "properties": {
          "type": { "type": "string" },
          "url": { "type": "string" }
        }
      },
      "Person": {
        "type": "object",
        "properties": {
          "Id": { "type": "string" },
          "Name": { "type": "string" },
          "First Name": { "type": "string" },
          "Lastname": { "type": "string" },
          "attributes": { "$ref": "#/components/schemas/Attributes" }
        },
        "description": "Account Object"
      },
      "Address": {
        "type": "object",
        "properties": {
          "Id": { "type": "string" },
          "Street": { "type": "string" },
          "Post Code": { "type": "string" },
          "City": { "type": "string" },
          "Country": { "type": "string" },
          "attributes": { "$ref": "#/components/schemas/Attributes" }
        },
        "description": "Address Object"
      }
    }
  }
}

这样所有用到attributes的地方都会引用同一个Schema,NSwag只会生成一个Attributes类。

2. 配置NSwagStudio的类型合并选项

如果无法修改OpenAPI文档,可在NSwagStudio里启用类型合并:

  • 打开NSwagStudio,切换到CSharp Client选项卡
  • 找到Type Generation部分,勾选Merge identical types选项
  • 还可以调整Type Name Generator的设置,确保相同结构的类型生成一致的名称

注意:这个选项可能会有边缘情况,比如某些结构看似相同但实际有细微差异(比如nullable设置),需要测试验证。

内容的提问来源于stack exchange,提问作者user3644868

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:35:24