swagger-codegen 的 readOnly 模型属性处理与 HasOnlyReadOnly 模型剖析
开发工具代码生成API设计【免费下载链接】swagger-codegenswagger-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 仓库中 Java 客户端示例的模型文档 HasOnlyReadOnly.md 为切入点结合对应的 OpenAPI/Swagger 定义与 Java 源码实现深入剖析「全部属性均为只读readOnly」的模型在代码生成过程中的识别、文档呈现与访问器生成规则。读完本文你将掌握如何在 Swagger/OpenAPI 定义中声明 readOnly 属性、swagger-codegen 如何在模型文档中标注只读字段、hasOnlyReadOnly标志与readOnlyVars列表的底层计算逻辑以及为何生成的 Java 类只有 getter 而没有 setter。一、HasOnlyReadOnly 模型是什么HasOnlyReadOnly是 swagger-codegen 官方测试夹具fixture中的专用模型用于验证代码生成器对「全部属性均为只读」这类极端模型形态的处理能力。它只包含两个String类型的属性属性类型说明备注barString—[optional]fooString—[optional]注意这里的备注列只有[optional]没有[readonly]标记。这是本文后续要重点剖析的一个有趣细节——尽管该模型的全部属性在定义中都被标记为readOnly: true但其模型文档表格中并未输出[readonly]标注。该模型在仓库的多个版本定义中均有出现例如 v2 的 petstorefake.yaml 与 samplesServers.yaml以及 v3 的 petstore3fake.yaml 与 petstoreMixed3.yaml。以 v2 定义为例hasOnlyReadOnly: type: object properties: bar: type: string readOnly: true foo: type: string readOnly: true模型名 HasOnlyReadOnly 即 Has Only Read-Only (properties) 的缩写语义直白该模型的所有属性都只读。二、readOnly 属性在 Swagger/OpenAPI 定义中的声明方式2.1 属性级声明在 OpenAPI/Swagger 2.0 与 OpenAPI 3.x 中readOnly是一个布尔型的属性修饰符声明在 schema 属性的同一层级bar: type: string readOnly: true其语义如下readOnly: true表示该属性只能出现在响应response中不应出现在请求request体中该属性不可由客户端提交因此生成的客户端模型通常不为其生成 setter / 写方法默认值为false未声明时按可读写处理。2.2 与其他修饰符的组合在夹具中readOnly常与其他修饰符组合出现用于覆盖更多测试场景例如 v2 petstorefake.yaml 中的Name模型Name: description: Model for testing model name same as property name required: - name properties: name: type: integer format: int32 snake_case: readOnly: true type: integer format: int32 property: type: string 123Number: type: integer readOnly: true可以看到readOnly与type、format同级并列同一模型中也可以混排只读与非只读属性如ReadOnlyFirst模型同时含只读的bar与可读写的baz见 petstorefake.yaml。这些夹具共同组成了 swagger-codegen 对只读属性处理逻辑的回归测试集。三、生成文档表格pojo_doc.mustache 模板解析模型文档如本文主题的HasOnlyReadOnly.md并非手工编写而是由代码生成器根据模板渲染输出。对应的模板是 pojo_doc.mustache# {{classname}} ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- {{#vars}}**{{name}}** | ... | {{description}} | {{^required}} [optional]{{/required}}{{#readOnly}} [readonly]{{/readOnly}} {{/vars}}表格的 Notes 列由两个条件片段拼接而成{{^required}} [optional]{{/required}}——当属性非必填时输出[optional]{{#readOnly}} [readonly]{{/readOnly}}——当属性标记为只读时输出[readonly]。该模板适用于所有语言变体的 pojo 文档生成不仅限于 Java同一模型在 bash、C#、Go、JavaScript、Perl、PHP、Python、Ruby、Swift 等客户端的docs/HasOnlyReadOnly.md均由它渲染。3.1 为什么本例没有[readonly]标注回到本文主题文档 HasOnlyReadOnly.md其 Notes 列只有[optional]没有[readonly]。这说明模板渲染时{{#readOnly}}条件为假——在 Mustache 模板中布尔值false与空值都会使区块不渲染。由此可以推断该文档是由一个未将isReadOnly透传到模板readOnly变量的版本生成的。也就是说这份样例文档是某一历史版本的生成产物而非按当前仓库源码重新生成的快照当前仓库中pojo_doc.mustache对只读属性的标注逻辑已演进详见下文第四节与第五节。这也提醒读者samples/目录下的生成物是「固定快照」不能仅凭它们断定代码生成器当前的行为需要结合modules/swagger-codegen中的源码与模板来判断。四、底层模型readOnlyVars 与 hasOnlyReadOnly 的计算逻辑4.1 CodegenProperty 的 isReadOnly 标记从 Swagger 定义到内部代码生成模型CodegenModel / CodegenProperty的转换由 DefaultCodegen.java 完成。isReadOnly字段的赋值逻辑如下DefaultCodegen.javaif (p.getReadOnly() ! null) { property.isReadOnly p.getReadOnly(); }即定义中显式给出readOnly布尔值时直接透传到内部模型CodegenProperty.isReadOnly。4.2 hasOnlyReadOnly 标志默认 true遇到可写属性才置 falseCodegenModel中专门定义了一个布尔标志hasOnlyReadOnlyCodegenModel.javapublic boolean hasOnlyReadOnly true; // true if all properties are read-only它的计算逻辑位于模型属性归集阶段DefaultCodegen.java// set models hasOnlyReadOnly to false if the property is read-only if (!Boolean.TRUE.equals(cp.isReadOnly)) { m.hasOnlyReadOnly false; }结合默认值true可知其语义为遍历模型全部属性一旦发现任何一个属性不是只读就将hasOnlyReadOnly置为false。因此全部属性只读 →hasOnlyReadOnly true只要存在一个可读写属性 →hasOnlyReadOnly false。这与模型名HasOnlyReadOnly的语义完全对应HasOnlyReadOnly模型的hasOnlyReadOnly必然为true而同时含bar只读与baz可读写的ReadOnlyFirst模型则为false。4.3 属性列表的划分readOnlyVars 与 readWriteVars在同一个归集循环中属性还会被划分进两个列表DefaultCodegen.java// if readonly, add to readOnlyVars (list of properties) if (Boolean.TRUE.equals(cp.isReadOnly)) { m.readOnlyVars.add(cp); } else { // else add to readWriteVars (list of properties) m.readWriteVars.add(cp); }两个列表的职责定义于 CodegenModel.javareadOnlyVars只读属性列表用于模板中「仅展示/仅反序列化」类逻辑readWriteVars可读写属性列表用于「请求体 / 可提交字段」类逻辑。对于HasOnlyReadOnly模型readOnlyVars包含bar与foo两个属性readWriteVars为空。五、Java 客户端readOnly 属性只生成 getter不生成 setter5.1 pojo.mustache 的条件渲染Java 客户端的模型模板为 pojo.mustache其中对每个属性变量做了三段式条件渲染链式fluent写入方法——仅在{{^isReadOnly}}时生成pojo.mustache{{#vars}} {{^isReadOnly}} public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} {{name}}; return this; } ... {{/isReadOnly}}getter——无条件生成pojo.mustachepublic {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{getter}}() { return {{name}}; }setter——仅在{{^isReadOnly}}时生成pojo.mustache{{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} {{name}}; } {{/isReadOnly}}结论明确readOnly 属性保留 getter供响应读取但被模板显式跳过 fluent 写入方法与 setter从而保证客户端不会向服务端提交只读字段。5.2 生成的 HasOnlyReadOnly.java 实证以上规则在生成的 Java 类中得到了直接印证HasOnlyReadOnly.java 中两个字段均以JsonProperty声明L29-L33只生成了getBar()L40-L42与getFoo()L49-L51两个 getter没有任何 setter也没有链式写入方法equals/hashCode/toString均由Objects工具基于两个字段实现L54-L93。同样的「只有 getter、没有 setter」结构也出现在仓库中其他语言/变体的生成物中例如 HasOnlyReadOnly.swift、HasOnlyReadOnly.php、HasOnlyReadOnly.js以及服务端模型如 HasOnlyReadOnly.java说明该行为是生成器层面的通用约定而非特定语言特例。5.3 生成该示例的完整 CLI 命令HasOnlyReadOnly的 Java 示例位于samples/client/petstore/java/jersey2-java8其生成过程对应 swagger-codegen CLI 的典型用法以 v2 定义与 java 生成器为例java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ -i fixtures/immutable/specifications/v2/petstorefake.yaml \ -l java \ --library jersey2 \ --additional-properties java8true \ -o samples/client/petstore/java/jersey2-java8关键参数说明-i输入 Swagger/OpenAPI 定义文件v2 或 v3 均可本仓库同时维护 v2 夹具 与 v3 夹具-l java目标语言生成器--library jersey2选择 Jersey 2 客户端库变体jersey2-java8 即基于此并叠加 Java 8 特性--additional-properties java8true启用 Java 8 语法特性如java.time日期类型这正是 jersey2-java8 与 jersey2 示例的差异点-o输出目录。同一petstorefake.yaml定义在仓库中被反复用于生成 java/okhttp-gson、java/resttemplate、java/retrofit2 等十余种 Java 变体以及 Python、Ruby、Swift、Go 等其它语言客户端是验证「同一模型定义、多语言生成一致性」的核心夹具。六、如何验证与证据如果希望自行验证上述行为仓库提供了完整的证据链定义侧阅读 petstorefake.yaml 中hasOnlyReadOnly模型的readOnly: true声明文档侧对比本主题文档 HasOnlyReadOnly.md 与模板 pojo_doc.mustache 的 Notes 列拼接规则源码侧追踪 DefaultCodegen.java 中hasOnlyReadOnly与readOnlyVars/readWriteVars的赋值以及 pojo.mustache 对isReadOnly的条件渲染产物侧核对 HasOnlyReadOnly.java 只有 getter、没有 setter 的最终形态。七、小结HasOnlyReadOnly模型是 swagger-codegen 中一个设计精巧的边界测试用例它验证了以下核心行为定义层readOnly: true作为属性修饰符声明只读语义中间层DefaultCodegen将定义标记透传为CodegenProperty.isReadOnly并据此维护readOnlyVars/readWriteVars两个列表与hasOnlyReadOnly总标志模板层pojo.mustache对isReadOnly条件渲染只读属性仅生成 getter、跳过 setter 与链式写入方法产物层最终 Java 类只有getBar()/getFoo()天然符合「只读属性仅可读取、不可提交」的 API 契约。同时对比当前模板 pojo_doc.mustache 与历史快照文档的差异可以看出samples/中的生成物是固定快照理解 swagger-codegen 的真实行为应以modules/swagger-codegen下的源码与模板为准。读者如需在自己的项目中应用这一机制只需在 OpenAPI 定义中对服务端生成的字段标注readOnly: true即可获得「响应可读、请求不可提交」的客户端模型从代码层面杜绝客户端误提交只读字段的问题。赞分享开发工具代码生成API设计【免费下载链接】swagger-codegenswagger-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 中 readOnly 属性的生成机制以 C 客户端 HasOnlyReadOnly 模型为例swagger codegen 中 readOnly 属性的生成机制以 C 客户端 HasOnlyReadOnly 模型为例 HasOnlyReadOnly开发工具代码生成API设计Swagger Codegen 中的 readOnly 模型生成详解以 HasOnlyReadOnly 为例Swagger Codegen 中的 readOnly 模型生成详解以 HasOnlyReadOnly 为例 HasOnlyReadOnly 是 Swagge开发工具代码生成API设计swagger-codegen 生成 C 只读属性模型以 HasOnlyReadOnly 为例解读 readOnly 语义的实现swagger codegen 生成 C 只读属性模型以 HasOnlyReadOnly 为例解读 readOnly 语义的实现 导读 本文以 swagger开发工具代码生成API设计创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

STM32嵌入式入门指南:从内核架构到开发环境搭建与实战

STM32嵌入式入门指南:从内核架构到开发环境搭建与实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 1:18:25 阅读更多 →
e稿核心卖点梳理 一站式AI论文写作工具优势解析

e稿核心卖点梳理 一站式AI论文写作工具优势解析

当前AI学术写作工具市场核心竞争维度2026年中文学术写作工具市场进入精细化发展阶段,伴随科研投入持续增加、学术出版规范不断完善,用户对学术写作工具的需求不再局限于单一的降重、内容生成功能,而是向全流程覆盖、垂直场景适配、合规安全等方向升级。据2026年学术工具用户需求…

2026/9/25 1:17:24 阅读更多 →
2026常州车灯升级哪家好|哪家靠谱|哪家专业|哪家性价比高?车灯改装推荐武进区【光遇车灯】

2026常州车灯升级哪家好|哪家靠谱|哪家专业|哪家性价比高?车灯改装推荐武进区【光遇车灯】

不少车主晚上开车,经常遇到原车灯光亮度不足、光线发散,雨天雾天看不清路面,远光聚光效果差,甚至年审灯光检测不过关的情况。想要改善夜间行车视野,一套靠谱的透镜产品、专业的施工技术以及正规的改装门店,…

2026/9/25 1:17:24 阅读更多 →

最新新闻

运营人必备的四大核心思维解析

运营人必备的四大核心思维解析

1. 运营人必备的四大核心思维解析在互联网行业摸爬滚打这些年,我见过太多运营新人把精力都花在学习各种工具和技巧上,却忽视了最基础的思维建设。就像盖房子不打地基,表面功夫做得再漂亮也经不起市场考验。今天我要分享的这四个思维模型&…

2026/9/25 6:47:17 阅读更多 →
Learn Harness Engineering 实战第 02 讲:构建 Agent 可读工作区,让新会话无缝续跑

Learn Harness Engineering 实战第 02 讲:构建 Agent 可读工作区,让新会话无缝续跑

【免费下载链接】learn-harness-engineering Harness engineering beginner tutorial, from 0 to 1 项目地址: https://gitcode.com/gh_mirrors/le/learn-harness-engineering 点击查看 免费下载 导读 本文对应仓库中《Project 02: Make the Project Readable and…

2026/9/25 6:47:17 阅读更多 →
零和博弈:从理论到实践的竞争哲学

零和博弈:从理论到实践的竞争哲学

1. 零和博弈的本质与哲学内涵零和博弈这个概念最早源于博弈论,但它的哲学意义远超出了数学模型的范畴。在棋牌游戏中,我们最直观地感受到这种"你赢我就输"的对抗关系。但把这个概念放到更广阔的人生和社会层面来看,会发现它揭示了资…

2026/9/25 6:47:17 阅读更多 →
华为悦盒EC6108V9刷机实战:海思Hi3798MV100通刷固件与短接救砖全攻略

华为悦盒EC6108V9刷机实战:海思Hi3798MV100通刷固件与短接救砖全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:47:17 阅读更多 →
Mage AI 数据集成实战指南:从源码调试 Source 与 Destination 的完整开发流程

Mage AI 数据集成实战指南:从源码调试 Source 与 Destination 的完整开发流程

数据工程数据编排ETL任务调度批处理流处理数据集成后端 【免费下载链接】mage-ai 🧙 Build, run, and manage data pipelines for integrating and transforming data. 项目地址: https://gitcode.com/gh_mirrors/ma/mage-ai 点击查看 免费下载 本指南以…

2026/9/25 6:47:17 阅读更多 →
基于SpringBoot+Vue的科普平台的设计与实现

基于SpringBoot+Vue的科普平台的设计与实现

一、项目简介为满足大众在线获取科学知识、浏览科普文章、互动交流的需求,本项目设计并实现了基于SpringBootVue的科普资讯平台。系统采用前后端分离架构,后端使用SpringBootMyBatis实现业务逻辑与数据持久化,前端通过Vue搭建交互页面&#x…

2026/9/25 6:46:17 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →