Swagger Codegen C 客户端模型文档解析:以 HasOnlyReadOnly 为例理解 readOnly 属性的生成与使用
2026/9/24 11:03:21 网站建设 项目流程
  • 开发工具
  • 代码生成
  • API设计

【免费下载链接】swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.

项目地址:https://gitcode.com/gh_mirrors/sw/swagger-codegen
点击查看免费下载

导读

本文以 swagger-codegen 为 C# 客户端生成的模型文档HasOnlyReadOnly.md为切入点,讲解 OpenAPI/Swagger 定义中readOnly模型属性如何被模板引擎转化为 C# 属性文档与代码实现。通过对照生成源码、Mustache 模板与测试用例,读者可以掌握模型文档的属性表规范、只读属性的落地形态,以及如何从生成的 C# 客户端中正确使用这类模型。

一、文档出处:自动生成的模型文档

HasOnlyReadOnly.md位于 samples/client/petstore/csharp/SwaggerClient/docs/ 目录,是 swagger-codegen 在处理 Petstore 测试规格(fixtures/immutable/specifications/v2/petstore.json)时,为 C# 语言客户端自动生成的一系列模型文档之一。与该文档同级的还有Pet.mdOrder.mdReadOnlyFirst.md等 40 余个模型文档,以及PetApi.mdStoreApi.mdUserApi.md等 API 文档。

这些文档不是手写的,而是由模板引擎渲染生成的。其源头模板位于 modules/swagger-codegen/src/main/resources/csharp/model_doc.mustache,这意味着:只要修改 OpenAPI 定义并重新执行代码生成,模型文档会自动同步更新,这正是 swagger-codegen「模板驱动引擎」(template-driven engine)设计理念的直接体现。

二、模型属性表:完整继承原文档内容

HasOnlyReadOnly.md的核心内容是一张模型属性表,原文档完整内容如下:

# IO.Swagger.Model.HasOnlyReadOnly ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Bar** | **string** | | [optional] **Foo** | **string** | | [optional] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

该表包含 4 列,含义如下:

列名含义
Name属性名,对应 JSON 序列化字段名(barfoo),在文档中以粗体展示
Type属性数据类型,此处两个属性均为 C# 的string(即 OpenAPI 中的type: string
Description属性描述,取自 OpenAPI 定义中的description字段,本模型中未填写
Notes附加标注,用于标记属性特性,例如[optional](非必填)、[readonly](只读)、[default to xxx](默认值)

对照模板 model_doc.mustache 可以看到 Notes 列的生成逻辑:

{{^required}}[optional] {{/required}}{{#readOnly}}[readonly] {{/readOnly}}{{#defaultValue}}[default to {{{.}}}]{{/defaultValue}}

即:属性在 OpenAPI 定义中未声明required: true时输出[optional];声明readOnly: true时输出[readonly];声明default时输出[default to ...]

值得注意的细节是:HasOnlyReadOnly的两个属性BarFoo在文档 Notes 列中仅标注为[optional],并没有出现[readonly]标注。这一现象源于 OpenAPI v2 规范的一个特性:readOnlyrequired是两个独立的维度,只读属性通常不会同时标记为必填,因此按模板逻辑只会输出[optional]。但只读语义仍然会传递到生成的 C# 代码中(详见下文第三节)。

三、源码级验证:只读属性在 C# 中的落地形态

模型文档描述的BarFoo两个属性,对应的生成源码位于 samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger/Model/HasOnlyReadOnly.cs。关键代码片段如下:

[DataContract] public partial class HasOnlyReadOnly : IEquatable<HasOnlyReadOnly>, IValidatableObject { [JsonConstructorAttribute] public HasOnlyReadOnly() { } /// <summary> /// Gets or Sets Bar /// </summary> [DataMember(Name="bar", EmitDefaultValue=false)] public string Bar { get; private set; } /// <summary> /// Gets or Sets Foo /// </summary> [DataMember(Name="foo", EmitDefaultValue=false)] public string Foo { get; private set; } ... }

从这个类可以提炼出 swagger-codegen 对 readOnly 属性的 C# 实现约定:

  1. 私有 setterBarFoo都使用{ get; private set; },即属性可以在类内部和序列化过程中赋值,但外部调用方无法直接修改。这正是「Has Only ReadOnly」这一模型命名的由来——整个模型的所有属性都是只读的,通常用于表示服务端返回、客户端只消费不改写的响应数据模型。
  2. 无参构造 + JsonConstructorAttribute:构造函数为空,反序列化由 Newtonsoft.Json 通过[JsonConstructorAttribute][DataMember]注解完成,客户端从服务端接收 JSON 响应时可以自动填充barfoo字段。
  3. 数据契约注解[DataContract]/[DataMember]将类映射到 JSON 契约,Name="bar"明确指定了 JSON 字段名(小写),EmitDefaultValue=false表示空值不会序列化输出。
  4. 值对象语义:类实现了IEquatable<HasOnlyReadOnly>IValidatableObject,并重写了EqualsGetHashCodeToStringToJson,使该模型可以作为值对象参与集合比较与调试输出。

四、模板与代码的对应关系:readOnly 如何贯穿生成链路

要从 OpenAPI 定义得到上面这份文档与代码,需要理解 swagger-codegen 的生成链路。整体流程可以概括为:

OpenAPI 定义(petstore.json) │ 解析 ▼ 代码模型对象(CodegenModel / CodegenProperty,含 readOnly 标记) │ 渲染 ▼ Mustache 模板(model.mustache + model_doc.mustache) │ 输出 ▼ C# 模型类 + 模型文档(HasOnlyReadOnly.cs + HasOnlyReadOnly.md)
  • 文档模板model_doc.mustache 负责渲染属性表格,Notes 列按requiredreadOnlydefaultValue三个条件组合标注;
  • 代码模板(同目录下的model.mustache)负责渲染类定义,其中readOnly属性会被渲染为私有 setter(private set),而非只读属性则会渲染为公共 setter;
  • 测试模板还会生成对应的单元测试骨架,本模型的测试位于 samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/HasOnlyReadOnlyTests.cs。

五、实战要点:在生成的 C# 客户端中使用只读模型

在实际项目中引用 swagger-codegen 生成的 C# 客户端时,针对HasOnlyReadOnly这类「仅只读属性」模型,需要遵循以下使用约束:

  1. 属性不可外部赋值:由于BarFoo的 setter 是私有的,调用方不能通过model.Bar = "value"写入数据。只能通过两种途径获得属性值:
    • 接收服务端 JSON 响应,由 Newtonsoft.Json 反序列化自动填充;
    • 通过ToJson()方法检查序列化后的 JSON 结构。
  2. 模型名称即语义提示HasOnlyReadOnly是 Petstore 测试规格中的特制模型,用于验证 swagger-codegen 对readOnly属性的处理是否完整——从文档表格、私有 setter、测试文件三处均可印证该能力。
  3. 配合ReadOnlyFirst理解混合场景:同目录下的 ReadOnlyFirst.md 展示了另一种形态——一个模型包含Bar(只读)与Baz(普通)两种属性。将其与HasOnlyReadOnly对比,可以更全面地理解readOnly标记在生成代码中的差异化处理。

六、更多参考

  • 查看完整模型文档目录:samples/client/petstore/csharp/SwaggerClient/docs/
  • 查看生成的 API 客户端入口与使用示例:samples/client/petstore/csharp/SwaggerClient/README.md
  • 查看 C# 代码生成模板:modules/swagger-codegen/src/main/resources/csharp/
  • 查看 Petstore 测试规格定义:fixtures/immutable/specifications/v2/petstore.json
  • 了解代码生成的更多配置项:docs/generators-configuration.md
  • 开发工具
  • 代码生成
  • API设计

【免费下载链接】swagger-codegen

swagger-codegen contains a template-driven engine to generate documentation, API clients and server stubs in different languages by parsing your OpenAPI / Swagger definition.

项目地址:https://gitcode.com/gh_mirrors/sw/swagger-codegen
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询