- 开发工具
- 代码生成
- 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.
导读
本文以 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.md、Order.md、ReadOnlyFirst.md等 40 余个模型文档,以及PetApi.md、StoreApi.md、UserApi.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 序列化字段名(bar、foo),在文档中以粗体展示 |
| 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的两个属性Bar、Foo在文档 Notes 列中仅标注为[optional],并没有出现[readonly]标注。这一现象源于 OpenAPI v2 规范的一个特性:readOnly与required是两个独立的维度,只读属性通常不会同时标记为必填,因此按模板逻辑只会输出[optional]。但只读语义仍然会传递到生成的 C# 代码中(详见下文第三节)。
三、源码级验证:只读属性在 C# 中的落地形态
模型文档描述的Bar、Foo两个属性,对应的生成源码位于 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# 实现约定:
- 私有 setter:
Bar和Foo都使用{ get; private set; },即属性可以在类内部和序列化过程中赋值,但外部调用方无法直接修改。这正是「Has Only ReadOnly」这一模型命名的由来——整个模型的所有属性都是只读的,通常用于表示服务端返回、客户端只消费不改写的响应数据模型。 - 无参构造 + JsonConstructorAttribute:构造函数为空,反序列化由 Newtonsoft.Json 通过
[JsonConstructorAttribute]与[DataMember]注解完成,客户端从服务端接收 JSON 响应时可以自动填充bar、foo字段。 - 数据契约注解:
[DataContract]/[DataMember]将类映射到 JSON 契约,Name="bar"明确指定了 JSON 字段名(小写),EmitDefaultValue=false表示空值不会序列化输出。 - 值对象语义:类实现了
IEquatable<HasOnlyReadOnly>和IValidatableObject,并重写了Equals、GetHashCode、ToString、ToJson,使该模型可以作为值对象参与集合比较与调试输出。
四、模板与代码的对应关系: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 列按
required、readOnly、defaultValue三个条件组合标注; - 代码模板(同目录下的
model.mustache)负责渲染类定义,其中readOnly属性会被渲染为私有 setter(private set),而非只读属性则会渲染为公共 setter; - 测试模板还会生成对应的单元测试骨架,本模型的测试位于 samples/client/petstore/csharp/SwaggerClient/src/IO.Swagger.Test/Model/HasOnlyReadOnlyTests.cs。
五、实战要点:在生成的 C# 客户端中使用只读模型
在实际项目中引用 swagger-codegen 生成的 C# 客户端时,针对HasOnlyReadOnly这类「仅只读属性」模型,需要遵循以下使用约束:
- 属性不可外部赋值:由于
Bar、Foo的 setter 是私有的,调用方不能通过model.Bar = "value"写入数据。只能通过两种途径获得属性值:- 接收服务端 JSON 响应,由 Newtonsoft.Json 反序列化自动填充;
- 通过
ToJson()方法检查序列化后的 JSON 结构。
- 模型名称即语义提示:
HasOnlyReadOnly是 Petstore 测试规格中的特制模型,用于验证 swagger-codegen 对readOnly属性的处理是否完整——从文档表格、私有 setter、测试文件三处均可印证该能力。 - 配合
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.
相关推荐
swagger-codegen 中 readOnly 属性的生成机制:以 C 客户端 HasOnlyReadOnly 模型为例
swagger codegen 中 readOnly 属性的生成机制:以 C 客户端 HasOnlyReadOnly 模型为例 HasOnlyReadOnly
开发工具代码生成API设计swagger-codegen 生成的模型文档详解:以 C 客户端 ReadOnlyFirst 为例解读 readOnly 属性语义
swagger codegen 生成的模型文档详解:以 C 客户端 ReadOnlyFirst 为例解读 readOnly 属性语义 导读 本文以 swagge
开发工具代码生成API设计swagger-codegen 生成 C 只读属性模型:以 HasOnlyReadOnly 为例解读 readOnly 语义的实现
swagger codegen 生成 C 只读属性模型:以 HasOnlyReadOnly 为例解读 readOnly 语义的实现 导读 本文以 swagger
开发工具代码生成API设计
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考