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

时间:2020-04-21 18:03:08

标签: protocol-buffers openapi proto grpc-go swagger-3.0

我的原始用例:

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

我不想在两个地方都维护我的服务器规范,也就是说,我不想同时维护原始文件(.proto)和大张旗鼓的规范(.json/.yaml)。由于我绝对必须编写原型文件才能生成gRPC服务器,因此我想自动化标准规格(OpenAPI3)。

我在哪里:

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

在尝试这样做时,我偶然发现了GoogleAPI googleapis/gnostic对该库的描述,

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

乍看之下,这似乎完全解决了我的问题,但事实证明,该库仅在协议缓冲区(protobuf)二进制(.pb)和张扬的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

它会生成以下swagger文件:

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)感谢最近的评论,很明显,.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规范转换为客户端/适用于几乎所有平台的服务器存根。但是,由于这不是最初提出的问题,因此问题仍然悬而未决。

1 个答案:

答案 0 :(得分:1)

尽管,您的要求似乎是要从PROTO获得YAML(OpenAPNv3)规范,但您可以签出此插件-gnostic-grpc-以确保gnostic的效果,即将YAML / JSON规范转换为proto和gRPC服务调用。