资讯动态

深入解析 HasOnlyReadOnly:swagger-codegen 生成只读模型(Java okhttp4-gson Parcelable 客户端)的完整链路

发布时间:2026/9/25 3:00:15 来源:尧图企业网站定制
开发工具代码生成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点击查看免费下载HasOnlyReadOnly是 swagger-codegen 在 Petstore 测试样例中用于验证「只读属性readOnly」建模能力的典型模型它的两个属性bar与foo在 OpenAPI 定义中都被标记为readOnly: true因此生成的 Java 类只有 getter、没有 setter。本文以仓库中生成的模型参考文档HasOnlyReadOnly.md为骨架结合对应的 OpenAPI 定义、生成后的 Java 源码以及 mustache 模板与生成器实现完整还原「定义 → 代码生成 → 文档输出 → Android Parcelable 使用」的整条链路帮助你理解只读模型在 JavaOkHttp4 Gson客户端中的落地形态。模型参考文档说了什么原文档是一份由 swagger-codegen 自动生成的模型属性参考页位于samples/client/petstore/java/okhttp4-gson-parcelableModel/docs/HasOnlyReadOnly.md。它列出了模型HasOnlyReadOnly的全部属性NameTypeDescriptionNotesbarString[optional]fooString[optional]关键信息有两层属性类型bar、foo均为String没有枚举、没有复合类型因此文档中不需要额外的「Enum」小节或指向其他模型文档的链接Notes 列两个属性都标记为[optional]意味着它们在 OpenAPI 定义中都不是必填required字段。这份文档与生成器模板 pojo_doc.mustache 一一对应——模板第 6 行定义了属性表格的渲染规则非必填字段输出[optional]只读字段输出[readonly]。当前仓库模板同时支持两种标注而该样例文档是历史版本生成的产物因此 Notes 列只出现了[optional]。源头OpenAPI 定义中的 readOnly 标记HasOnlyReadOnly并非凭空存在它来自 Petstore fake endpoints 测试规格。仓库中有两份互为对照的规格文件都定义了该模型Swagger 2.0 版本fixtures/immutable/specifications/v2/petstorefake.yamlhasOnlyReadOnly: type: object properties: bar: type: string readOnly: true foo: type: string readOnly: trueOpenAPI 3.0 版本fixtures/immutable/specifications/v3/petstore3fake.yaml结构与 2.0 完全一致仅外层从definitions换成了components/schemashasOnlyReadOnly: type: object properties: bar: type: string readOnly: true foo: type: string readOnly: true可以推断这个模型被刻意设计为「全部属性都是只读」用来端到端验证生成器对readOnly语义的处理。它在 Swagger 2.0 中通过 JSON Schema 风格的readOnly: true声明OpenAPI 3.0 中语义相同由Schema.readOnly表示。除上述两条 immutable fixture 外modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml等测试资源中也包含同名定义是生成客户端样例所使用的规格来源。生成结果一份只读的 Java 模型类从上述定义生成的 Java 类位于 HasOnlyReadOnly.java它实现了android.os.Parcelable因为样例开启了parcelableModeltrue。其核心结构如下public class HasOnlyReadOnly implements Parcelable { SerializedName(bar) private String bar null; SerializedName(foo) private String foo null; public HasOnlyReadOnly() { } ApiModelProperty(value ) public String getBar() { return bar; } ApiModelProperty(value ) public String getFoo() { return foo; } // ...equals / hashCode / toString / Parcelable 相关方法 }几个值得注意的实现细节字段与 JSON 序列化字段用 Gson 的SerializedName(bar)/SerializedName(foo)标注确保 JSON 键与 OpenAPI 属性名一致无 setter类里只有getBar()、getFoo()没有setBar()、setFoo()——这是只读属性的直接体现客户端无法在本地修改这两个字段的值空构造器提供无参构造配合 JSON 反序列化Gson 通过反射直接填充字段值语义equals/hashCode基于两个属性实现toString输出class HasOnlyReadOnly { bar: ..., foo: ... }形式的可读字符串。为什么没有 setter模板中的 isReadOnly 分支这一行为不是硬编码在样例里的而是由生成模板决定的。在 Java 生成器的 POJO 模板 pojo.mustache 中public {{{datatypeWithEnum}}} {{#isBoolean}}is{{/isBoolean}}{{getter}}() { return {{name}}; } {{^isReadOnly}} public void {{setter}}({{{datatypeWithEnum}}} {{name}}) { this.{{name}} {{name}}; } {{/isReadOnly}}模板先无条件生成 getter然后用{{^isReadOnly}}非只读条件控制 setter 的生成只有非只读属性才会得到 setter。HasOnlyReadOnly的两个属性都命中isReadOnly于是 setter 被整体跳过。更底层地生成器在解析模型属性时会维护三类列表。在 DefaultCodegen.java 中可以看到// if required, add to the list requiredVars if (Boolean.TRUE.equals(cp.required)) { m.requiredVars.add(cp); } else { // else add to the list optionalVars for optional property m.optionalVars.add(cp); } // 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); }即每个属性会被同时归类到requiredVars/optionalVars是否必填与readOnlyVars/readWriteVars是否只读两组集合供各语言的模板按需渲染。HasOnlyReadOnly的两个属性因此同时落入optionalVars与readOnlyVars最终反映为参考文档中的[optional]和 Java 类中「只有 getter」。Android Parcelable 支持模型如何在进程间传递由于样例名中的parcelableModel后缀生成的模型类还实现了android.os.Parcelable用于 Android 平台跨 Activity/Service 传递对象。Parcelable 部分同样来自模板pojo.mustache 及之后的段落生成到该类中的形态为public void writeToParcel(Parcel out, int flags) { out.writeValue(bar); out.writeValue(foo); } HasOnlyReadOnly(Parcel in) { bar (String) in.readValue(null); foo (String) in.readValue(null); } public int describeContents() { return 0; } public static final Parcelable.CreatorHasOnlyReadOnly CREATOR new Parcelable.CreatorHasOnlyReadOnly() { public HasOnlyReadOnly createFromParcel(Parcel in) { return new HasOnlyReadOnly(in); } public HasOnlyReadOnly[] newArray(int size) { return new HasOnlyReadOnly[size]; } };注意这里对每个属性依次执行out.writeValue(...)与in.readValue(...)读写顺序与属性声明顺序一致describeContents()返回 0 表示没有特殊内容描述非文件描述符类对象。也就是说即使是只读模型序列化/反序列化时字段仍然会被完整地写入和读出——只读约束的是业务层的 setter API而非底层数据传递。如何重新生成这个样例该样例对应的生成器是 Java 客户端生成器中的okhttp4-gsonlibrary。在 JavaClientCodegen.java 中okhttp-gson与okhttp4-gson的说明均注明HTTP client: OkHttp 4.10.0. JSON processing: Gson 2.8.1. Enable Parcelable models on Android using-DparcelableModeltrue.因此使用仓库中的 CLI 从上述 2.0 规格重新生成此样例等价于java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ -i fixtures/immutable/specifications/v2/petstorefake.yaml \ -l java \ --library okhttp4-gson \ -DparcelableModeltrue \ -o samples/client/petstore/java/okhttp4-gson-parcelableModel-DparcelableModeltrue会通过生成器的setParcelableModel(boolean)入口JavaClientCodegen.java写入附加属性additionalProperties.put(parcelableModel, true)从而让模板渲染出Parcelable相关代码。生成后模型参考页会被写入docs/HasOnlyReadOnly.md并登记在样例 README.md 的 Documentation for Models 列表中。实战如何使用只读模型HasOnlyReadOnly的典型使用场景是作为响应体response body模型——服务端返回bar、foo客户端只读取、不修改。用法如下import io.swagger.client.model.HasOnlyReadOnly; // 通过 API 调用拿到模型由 ApiClient 完成 JSON 反序列化 HasOnlyReadOnly result ...; // 只能读取 String bar result.getBar(); // 可能为 nulloptional 字段 String foo result.getFoo(); // 可能为 null // 无法编译通过不存在 setBar() / setFoo() // result.setBar(x); // 编译错误两个字段均为可选optional因此反序列化时如果 JSON 中缺少对应键字段保持nullgetBar()/getFoo()返回null。需要非空判断时直接判空即可无需额外初始化逻辑。小结HasOnlyReadOnly是一个麻雀虽小、五脏俱全的「只读模型」教学样例串起了 swagger-codegen 的完整链路定义侧readOnly: true标注属性v2 fixture / v3 fixture生成侧DefaultCodegen将属性归入readOnlyVarspojo.mustache用{{^isReadOnly}}跳过 setterpojo.mustache文档侧pojo_doc.mustache渲染属性表格并输出[optional]/[readonly]标注pojo_doc.mustache使用侧只读模型在 Android 上依然完整支持Parcelable可跨组件传递但只能读、不能写。理解这一链路后你在自己的 OpenAPI 定义中标记readOnly: true时就能准确预判生成代码的形态getter 存在、setter 消失、文档 Notes 列出现对应标注——这正是 swagger-codegen 以规格驱动、模板渲染的建模方式带来的可预测性。赞分享开发工具代码生成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 生成的 AnotherFakeApi Java 客户端okhttp4-gson Parcelable 版深度解析与调用实战Swagger Codegen 生成的 AnotherFakeApi Java 客户端okhttp4 gson Parcelable 版深度解析与调用实战 导开发工具代码生成API设计Semantica语义分块实战如何按实体边界切分文档而不割裂语义Semantica语义分块实战如何按实体边界切分文档而不割裂语义 做 RAG 或知识图谱构建时把长文档切成小块chunk是绕不开的第一步。Semanti开发工具代码生成API设计Swagger Codegen 生成的 User 模型解析以 okhttp4-gson-parcelableModel Java 客户端为例Swagger Codegen 生成的 User 模型解析以 okhttp4 gson parcelableModel Java 客户端为例 导读 User.开发工具代码生成API设计上一篇TypeORM 手工编写迁移Migration全指南migration:create 与 up/down 实战下一篇eslint-plugin-unicorn 规则实战no-invalid-remove-event-listener —— 拦截无效的事件监听器移除创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑