如何从 protobuf (.proto) 文件中生成 (.json/.yaml) 中的 swagger3 (OpenAPI3) 规范?

     2023-03-31     151

关键词:

【中文标题】如何从 protobuf (.proto) 文件中生成 (.json/.yaml) 中的 swagger3 (OpenAPI3) 规范?【英文标题】:How to generate swagger3 (OpenAPI3) spec in (.json/.yaml) from protobuf (.proto) files? 【发布时间】:2020-04-21 18:03:08 【问题描述】:

我原来的用例:

我正在使用gRPC 服务器(使用protobuf)在GO 中构建一个应用程序,并将其包装在HTTPS 服务器中(使用gin)。只有 HTTPS 服务器被发布到客户端以供使用(我的意思是我的应用程序可以通过 REST API 访问,然后实际上在 gRPC 端点上拨号),我使用Swagger OpenAPI3(版本 3)发布它是这里的主要要求)规范。 gRPC 和 HTTPS 都是必需的,任何解决方案都应遵循此架构。

我不想在两个地方维护我的服务器规范,即我不想同时维护 proto 文件 (.proto) 和 swagger 规范 (.json/.yaml)。由于我必须编写 proto 文件来生成 gRPC 服务器,因此我想自动生成 swagger 规范 (OpenAPI3)。

我在哪里:

我可以使用 grpc-gateway 库从 protobuf 文件 (.proto) 生成 swagger OpenAPI2 规范,类似于:grpc-rest-go-example。但我的要求是 OpenAPI3;更具体地说,我想在 OpenAPI3 中使用 oneOf 功能并从 proto 的 oneof 功能映射到它。 这在 OpenAPI2 中是不可能的,因为它不允许 API 具有多个类型定义的请求/响应主体,这是 OpenAPI3 通过启用 oneOf、anyOf 和 allOf 构造添加的功能。

在尝试这样做时,我偶然发现了 GoogleAPIs googleapis/gnostic 提供的这个库,其描述是:

此存储库包含一个 Go 命令行工具,可将 JSON 和 YAML OpenAPI 描述与等效的协议缓冲区表示形式相互转换。

乍一看,这似乎完全解决了我的问题,但事实证明,这个库只在协议缓冲区 (protobuf) 二进制 (.pb) 和 swagger OpenAPI2/OpenAPI3 (.json/.yaml) 文件之间相互转换,这给我带来了我的新问题。

例如对于以下.pb 文件:


�3.0.1�…�
�Example service��Example service description*�
�Example contact2=

Apache 2.0�/http://www.apache.org/licenses/LICENSE-2.0.html:�1.0�!
�//localhost:9999/example/api/v1"â�
�
�/exampleResource��"���Example API��Example API description*�example-operation2B
@
example-query��query��example-query description �R�
    Ê��stringBÇ��œ�
�200�”�
‘�
�OK�Š�
C
�application/json�/
-�+
)#/components/schemas/common.StatusMessage
C
�application/yaml�/
-�+
)#/components/schemas/common.StatusMessage�¥�
�400���
š�
�Bad Request�Š�
C
�application/json�/
-�+
)#/components/schemas/common.StatusMessage
C
�application/yaml�/
-�+
)#/components/schemas/common.StatusMessage*Y
W
U
�common.StatusMessage�=
;Ê��objectú�/
�
�message��
    ��string
�
�status��
    ��string

它会生成以下招摇文件:

openapi: 3.0.1
info:
  title: Example service
  description: Example service description
  contact:
    name: Example contact
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: "1.0"
servers:
- url: //localhost:9999/example/api/v1
paths:
  /exampleResource:
    get:
      summary: Example API
      description: Example API description
      operationId: example-operation
      parameters:
      - name: example-query
        in: query
        description: example-query description
        required: true
        schema:
          type: string
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
            application/yaml:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
        400:
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
            application/yaml:
              schema:
                $ref: '#/components/schemas/common.StatusMessage'
components:
  schemas:
    common.StatusMessage:
      type: object
      properties:
        message:
          type: string
        status:
          type: string

.pb 可能无法正常查看,请访问它here。所以像:

�status��
    ��string

看起来像:

<0x06>status<0x12><0x0b>
    Ê<0x01><0x06>string

对于上面的例子,我首先编写了 swagger 规范,然后生成了 .pb,但同样可以反过来做。

当前状态:

如果我有办法在 (.pb) 和 (.proto) 文件之间进行转换,则转换循环将关闭并完成 (.proto -> .pb -> .json/.yaml -> .pb -> .proto)。

我确信必须有一种方法来实现这一点,因此我的原始问题存在解决方案。但是我找不到任何可以做到这一点的文章或代码。 .pb.proto 文件之间是否有合理的方法来相互转换?

如果您对我的原始用例有完全不同的解决方案,也请随时分享。这会很有帮助。

提前致谢!

编辑:

(1) 感谢最近的 cmets,很明显 .pb.proto 之间的“转换”首先是一个荒谬的问题。但最初的问题仍然相同,即如何使用注释、标签或其他方式从 protobuf 文件 (.proto) 生成 swagger3 (OpenAPI3) 规范。 相应地更改问题标题。

(2) 就在我发布这个后的第二天,我碰到了gnostic-grpc 存储库,其中的描述是:

此工具将 OpenAPI v3.0 API 描述转换为 gRPC 服务的描述,该服务可用于使用 gRPC-JSON 转码实现该 API。

同样,这让我过早退出。实际上,这是一个 GSOC 项目,尽管这个存储库的想法令人惊叹,但它并没有满足 requirements 的要求。此外,这不是一个相互转换的库,对于任何生产用途都非常不成熟。事实上,它未能提供 OpenAPI3 规范的一些基本特性。

但是这个存储库正朝着正确的方向前进。我的结论是有一个自定义插件可以做到这一点,主要是通过扩展 GO 中的注释库。

(3) 显然,从 .proto 转换为 OpenAPI3 规范 (.yaml/.json) 没有好的和明显的候选对象,除了 gnostic-grpc,它非常不成熟,并且正在为任何类型的实际用途进行大量工作。

但是对于反向转换,即OpenAPI3规范(.yaml/.json)到.proto,在OpenAPITools下有一个很好的库叫做openapi-generator,它可以将OpenAPI v2/3规范转换为几乎所有平台的客户端/服务器存根.但由于这不是最初的问题,所以问题仍然悬而未决。

【问题讨论】:

您根本不会将 protobuf 有效负载 转换为 .proto;这并不意味着什么。有 2 种 protobuf 格式:(a) 二进制 protobuf 编码 - 这就是您在问题中所称的 .pb,以及 (b) 在 json 中表达相同意图的固执己见的 json 变体;在这种情况下(即 .proto 意味着完全不同的东西),你能澄清你想在这里做什么吗? 哦,好吧!我的确切用例是编写 proto 文件 -> 生成 gRPC 服务器 -> 生成 HTTPS 服务器并为服务器生成 swagger 规范。我知道这对于使用 grpc-gateway 库(在 .proto 文件中使用注释)的 openAPI2 是可能的,但是对于 OpenAPI3 找不到任何东西。我想使用注释、标签或其他方式将 .proto 转换为 OpenAPI3 规范。 grpc-gateway 有一个问题开放了几年来支持 openAPI v3:github.com/grpc-ecosystem/grpc-gateway/issues/441 我也需要这个。也许我们可以一起努力。由于它已经生成了 openAPIv2,因此它的提升似乎比从头开始编写要少。 我很乐意为此工作。目前我正在开发 python 脚本来进行这种相互转换,我将开源它,但是在更容易访问的存储库中更通用的解决方案将更加令人惊奇,无论如何,python 脚本只是一种解决方法。但是关于第二部分,我认为它肯定会比从头开始写东西要少,但还是很多,这很好!这是因为 OpenAPIv3 是高度向后不兼容的。 【参考方案1】:

虽然,您的要求似乎是从 PROTO 获取 YAML (OpenAPNv3) 规范,但您可以查看此插件 - gnostic-grpc - 用于 gnostic,它执行相反的操作,即从 YAML/JSON 规范转换为原型使用 gRPC 服务调用。

【讨论】:

是的,就在我发布这个问题的那天之后,我遇到了这个问题。尽管这个存储库的想法很神奇,但它还没有准备好使用。这是一个 GSOC 项目,有错误。正如你所说,它的转换是一种方式,而且是不完整的。它不支持大多数 openAPI 结构,并且它支持的结构没有利用 openAPI 3 功能。我得出的结论是,编写插件是最好的解决方案,这并不难。最重要的是,我决定为诺斯替教做出贡献,因为我喜欢这个想法。这是一个真实的用例,令人惊讶的是没有解决方案。 绝对如此。事实上,由于对 OpenAPI 的看似不完整或部分支持,我们一直在尝试使用它并陷入多重限制。但令人惊讶的是,不幸的是,除了这个之外,没有其他实现能像从 YAML 中获取 proto(特别是 gRPC)那样接近。 我在 GitHub 上也有一个 open question 。 @AnupamaDeshmukh 我是 gnostic-grpc 的主要贡献者之一。您能否更详细地说明什么对您不起作用?随意在存储库中打开问题。

如何从 proto 文件中使用 ProtoGen 生成结构

...布时间】:2013-08-2113:03:41【问题描述】:我们一直在使用protobuf-netProtoGen从*.proto文件生成C#.cs文件。我们想代替类来生成结构。例如[DataContract]publicstructEntity1[ProtoMember(1)]p 查看详情

如何使用 protobuf-net 处理 .proto 文件

】如何使用protobuf-net处理.proto文件【英文标题】:Howtoprocessa.protofileusingprotobuf-net【发布时间】:2010-05-1220:14:42【问题描述】:我已经开始使用protobuf-net库在我正在维护的一些程序之间进行通信。我还能够将消息从C#解码为Ruby。... 查看详情

从 protobuf-net 中的自定义 RuntimeTypeModel 生成 .proto 文件

】从protobuf-net中的自定义RuntimeTypeModel生成.proto文件【英文标题】:Generate.protofilefromacustomRuntimeTypeModelinprotobuf-net【发布时间】:2015-06-1715:59:19【问题描述】:使用protobuf-net,我希望从RuntimeTypeModel.Default以外的类型模型生成一个.pr... 查看详情

从不同的项目.Net访问protobuf

】从不同的项目.Net访问protobuf【英文标题】:Accessingprotobuffromdifferentproject.Net【发布时间】:2019-05-3018:59:23【问题描述】:我正在尝试使用gRPC构建一个大型系统。我有一个项目,我在其中定义了一个.proto文件。我创建了第二个项... 查看详情

如何从 Protocol Buffers .NET 代码生成 .proto 文件?

...题讨论】:【参考方案1】:“具有属性的类”是指适合protobuf-net的属性吗?如果 查看详情

如何在 Protobuf-net 中动态添加 Proto 成员

】如何在Protobuf-net中动态添加Proto成员【英文标题】:HowtodynamicallyaddProtoMembersinProtobuf-net【发布时间】:2013-09-2320:51:36【问题描述】:很久以前,正如@Marc在threads之一中所说,protobuf-net不支持动态。那个说法还有效吗?如果没有... 查看详情

.proto 文件中带有 oneof 的 Protobuf-net

】.proto文件中带有oneof的Protobuf-net【英文标题】:Protobuf-netwithoneofin.protofile【发布时间】:2015-02-0909:58:53【问题描述】:我正在使用来自protobuf-net的ProtoGen工具(版本1.0.0.280)从.proto文件生成.cs文件。但是,使用oneof关键字会导致... 查看详情

protobuf-net 继承在 .proto 文件中显示基类

】protobuf-net继承在.proto文件中显示基类【英文标题】:protobuf-netinheritanceshowsbaseclassin.protofile【发布时间】:2017-07-2808:23:25【问题描述】:我正在使用反射在运行时为protobuf-net构建运行时模型,而无需注释我需要序列化的类。我... 查看详情

protobuf(protocolbuffers).proto文件中的idl(interfacedefinitionlanguage接口定义语言)是什么?

文章目录.proto文件介绍在Google的ProtocolBuffers中,.proto文件使用的语言就是接口定义语言(IDL),它定义了要使用的数据类型、消息结构、服务等。然后可以使用特定的编译器将.proto文件转换为各种编程语言的源代... 查看详情

protobuf使用手册

Protobuf使用手册第1章定义.proto文件首先我们需要编写一个proto文件,定义我们程序中需要处理的结构化数据,在protobuf的术语中,结构化数据被称为Message。proto文件非常类似java或者C语言的数据定义,可以使用C或C++风格的注释。... 查看详情

使用 protobuf-net 生成 C# 时保留 proto 注释

】使用protobuf-net生成C#时保留proto注释【英文标题】:PreservingprotocommentswhengeneratingC#withprotobuf-net【发布时间】:2013-02-1210:57:04【问题描述】:我们正在使用protobuf-net来处理C#应用程序中的协议缓冲区需求。由于我们与其他非托管... 查看详情

go使用protobuf(代码片段)

本文更新于2019-01-03。从https://github.com/protocolbuffers/protobuf/releases下载protoc(如:Windows则下载protoc-3.6.1-win32.zip)。protoc命令位于bin目录下。gogetgithub.com/golang/protobuf。编译github.com/golang/protobuf/protoc-gen-go。因protoc需调用protoc-gen-go,... 查看详情

protoeditor-如何在unity中实现一个protobuf通信协议类编辑器(代码片段)

文章目录简介Protobuf语法规则ProtoEditor实现创建窗口定义类、字段增删类编辑字段导入、导出Json文件生成.proto文件生成.bat文件简介在Socket网络编程中,假如使用Protobuf作为网络通信协议,需要了解Protobuf语法规则、编写.pro... 查看详情

protobuf-net 生成的 .proto 文件中的字段命名约定不正确?

】protobuf-net生成的.proto文件中的字段命名约定不正确?【英文标题】:Incorrectnamingconventionforfieldsin.protofilesgeneratedbyprotobuf-net?【发布时间】:2013-07-2414:31:46【问题描述】:我刚刚开始使用GoogleProtocolBuffers和MarcGravell令人敬畏的proto... 查看详情

项目中使用protobuf

在互种系统中数据通信或数据交换可以使用protobuf,他比json、xml的数据量要小一些。另外因为消息要单独写一个.proto文件,来生成各平台的代码,所以对跨平台通信来说也比较友好。一。使用方法  1.编写.proto文件,定义格式... 查看详情

protobuf 和 Visual Studio 无缝集成 - 监控 proto 文件更改 [重复]

】protobuf和VisualStudio无缝集成-监控proto文件更改[重复]【英文标题】:protobuf&visualstudioseamlessintegration-monitorprotofilechanges[duplicate]【发布时间】:2020-03-0910:15:06【问题描述】:我正在将protobuf添加到我的C++项目中(如果您询问,... 查看详情

在 vb.net 中使用 .proto 文件

...布时间】:2018-03-0815:20:46【问题描述】:我正在尝试掌握protobuf-net,因为我相信这是帮助我反序列化protobuf创建的文件的正确工具。我已设法找到与相关文件相关的.proto文件,因此我相信我拥有处理该文件所需的所有原始信息。... 查看详情

protobuf语法指南(代码片段)

英文: ProtoBuffersLanguageGuide本指南描述了怎样使用protocolbuffer语法来构造你的protocolbuffer数据,包括.proto文件语法以及怎样生成.proto文件的数据访问类。(本文只针对proto2的语法)本文是一个参考指南——如果要查看如何使用本文... 查看详情