Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Need Help] How can I generate Swagger/OpenAPI v3 spec from .proto files and vice versa #162

Open
krishna-birla opened this issue Apr 20, 2020 · 24 comments

Comments

@krishna-birla
Copy link

krishna-birla commented Apr 20, 2020

It seems that only binary protocol buffers are supported for interconversion between protobuf and swagger. How can I convert binary protocol buffers (.pb) to and from proto3 protocol buffers (.proto), is that even a sane question to ask.

Moreover, my final intent is to be able to interconvert between .proto and OpenAPI2/3 spec (.json/.yaml) files, either using annotations in the .proto file, some tags or otherwise.

Thanks in advance!

Edits:

Modifying the issue title a little to highlight the use case much better.

External links:

Stack Overflow | How to generate swagger3 (OpenAPI3) spec in (.json/.yaml) from protobuf (.proto) files?

@LorenzHW
Copy link
Collaborator

You can go from .json/.yaml to .proto with gnostic-grpc.

@krishna-birla
Copy link
Author

krishna-birla commented Apr 22, 2020

Thanks for the quick response!!

This project is a very nice initiative, and I am super glad to see it incubate in GSOC! But there are a few issues that I think are fundamental given the description of the project is clear:

This tool converts an OpenAPI v3.0 API description into a description of a gRPC service that can be used to implement that API...

So

So a major feature added in OpenAPI3 over the previous version 2 was the ability to have multiple schemas for the same HTTP verb + path, using the oneOf, anyOf and allOf constructs. There are constructs in protobuf such as oneOf, using different combinations of these can simulate all OpenAPI3 constructs. The current version of the project does not support it.

The current conversion logic loses a lot of information from the spec (it is lossy), and hence converting back is neither possible nor supported (as of now). So generating servers and clients from these specs is not possible.

Moreover, some of my test examples were missing some tags from the annotations like body tag in results. A lot of swagger3 fields are today not supported. And above all, this is NOT an inter-conversion library, it does not convert to and from, where as the more practical use case is proto to swagger3 and not the other way around, since most implementations wrap an HTTP(S) server around gRPC server, and not the other way around.

But

But clearly this project is WIP, and what it already does is very helpful in some use cases. I would love to contribute to the project and be a part of it. This has good scope, it is trying to deal with a problem everyone has but no one talks about.

Meanwhile

Meanwhile, are there anymore "production" usable alternatives to solve my original problem?

@balnice
Copy link

balnice commented May 3, 2020

@krishna-birla My team is also looking for the same and we've found 2 more alternatives for evaluation so far:

Hope these help.

@krishna-birla
Copy link
Author

krishna-birla commented May 3, 2020

Thanks @balnice
The second option looks promising, but the fundamental requirement of interconversion is still on hang. These libraries don't convert .proto to OpenAPI v3 spec, and only do it the other way around.

The most common and main use case is to wrap an HTTPS server around a gRPC server. This means that the developer writes the .proto files and the rest of the steps (i.e. generate gRPC server, generate gRPC client, generate OpenAPI v3 spec, generate HTTPS server, generate HTTPS client) should be automated.

The second repository you suggested definitely helps, but the question still remains open.

@krishna-birla krishna-birla changed the title [Need Help] How can I generate .proto files from swagger spec and vice versa [Need Help] How can I generate Swagger/OpenAPI v3 spec from .proto files and vice versa May 3, 2020
@shikag
Copy link

shikag commented May 14, 2020

@krishna-birla Were you able to resolve this? I also have the same thing: Rest APIs in Java Spring Boot using Protobuf classes as arguments, and looking to generate Swagger UI.

Have you tried using protoc to generate .pb files from .proto and then using gnostic to generate OpenAPI V3 (something like reverse of this)

@krishna-birla
Copy link
Author

@shikag It didn't work for me, I also thought that .pb is just intermediate code for protobuf, but it doesn't seem like it.

@shellsong
Copy link

shellsong commented Jun 10, 2020

@krishna-birla have you try this which can convert *.proto to swagger json schema

@krishna-birla
Copy link
Author

@shellsong Yes, it supports OpenAPIv2, I am looking for v3.

@shikag
Copy link

shikag commented Jun 15, 2020

Thanks!

@mpokryva
Copy link

You can run the generated OpenAPI v2 code through https://github.com/getkin/kin-openapi/tree/master/openapi2conv to get OpenAPI v3 code. This would work if you don't want to build something "cleaner," and you don't need any OpenAPI v3 features, just the syntax.

@krishna-birla
Copy link
Author

I need the anyOf and oneOf features. That is the catch.

@mpokryva
Copy link

mpokryva commented Jun 17, 2020

I see. One thing that should be easier to do would be to convert the v2 spec to v3 as I said above and then fork grpc-gateway and use gnostic's v3 proto spec to implement anyOf and oneOf annotations. See https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-swagger/options/annotations.proto for the v2 equivalent. Not "clean," but it should work.

@timburks
Copy link
Contributor

Hi @krishna-birla, do you have any end-to-end examples that illustrate your goals? Specifically I'm curious to see an OpenAPI spec that has examples of your usage of anyOf and oneOf, and even better if you have a corresponding .proto file - I'm guessing that since there's no automated conversion available, you might be manually mapping from proto to OpenAPI in handwritten code. Anyway, I think an example would be very helpful. Thanks!

@krishna-birla
Copy link
Author

krishna-birla commented Jun 22, 2020

Hi @timburks
Thanks for the prompted reply.

A simple example could be something like this:
from

...
message CreateAnimalRequest {
  oneof Aminals {
    Cat cat = 1;
    Dog dog = 2;
    Lizard lizard = 3;
  }
}
...

to

...
requestBody:
        content:
          application/json:
            schema:
              oneOf:
              - $ref: '#/components/schemas/Cat'
              - $ref: '#/components/schemas/Dog'
              - $ref: '#/components/schemas/Lizard'
          application/yaml:
            schema:
              oneOf:
              - $ref: '#/components/schemas/Cat'
              - $ref: '#/components/schemas/Dog'
              - $ref: '#/components/schemas/Lizard'
...

The application/yaml and application/json parts can be taken from tags, so please ignore those.

Yes, I am forced to write a script of my own given the lack of a library, but I would prefer using one from openAPI or googleapis. I will be more than happy to contribute!

@timburks
Copy link
Contributor

timburks commented Jun 25, 2020

@krishna-birla One of the basic limitations currently is that the conversion from .proto (gRPC) to REST/JSON is done in a standard way that probably does not support oneofs in proto message bodies (I haven't tried to verify this but am not aware of this ever being done). So perhaps before we can usefully generate an OpenAPI v3 model, we should verify that an appropriate REST API is being created. Do you know if HTTP transcoding (described in AIP-127) will usefully transcode .protos like your sample?

@krishna-birla
Copy link
Author

Sorry for the delayed response, I will investigate deeper and reply soon.

@krishna-birla
Copy link
Author

krishna-birla commented Jul 15, 2020

@timburks Apologies for the delayed response.

The transcoding in https://google.aip.dev/127 may not be able to completely cater to the oneOf use case. Currently, annotations is a map, and takes HTTP spec of the GRPC. But it does not support accepting multiple types of bodies for the GRPC method. This gap prevents from using one of the key additions/features from OpenAPI v3.

For example, something expected as shown in:

rpc CreateBook(CreateBookRequest) returns (Book) {
  option (google.api.http) = {
    post: "/v1/books/*"
    body: "book"
  };
}

message CreateBookRequest {
  // The publisher who will publish this book.
  // When using HTTP/JSON, this field is automatically populated based
  // on the URI, because of the `{parent=publishers/*}` syntax.
  string parent = 1;

  // The type of the book, academic or fun time.
  // When using HTTP/JSON, this field is populated based on the HTTP body,
  // because of the `body: "book"` syntax.
  string bookType = 1;

  // The book to create.
  // When using HTTP/JSON, this field is populated based on the HTTP body,
  // because of the `body: "book"` syntax.
  // If body is an academic book, bookA is populated
  // If body is a fun time book, bookB is populated
  oneOf BookTypes {
    BookAcademic bookA = 2;
    BookFunTime bookF = 3;
  }

  // The user-specified ID for the book.
  // When using HTTP/JSON, this field is populated based on a query string
  // argument, such as `?book_id=foo`. This is the fallback for fields that
  // are not included in either the URI or the body.
  string book_id = 4;
}

@krishna-birla
Copy link
Author

Also, similarly HTTP/YAML will also be supported for above AIPs, right?

@zwiedmann-isp
Copy link

Same desire, currently using protoc-gen-swagger since we don't currently have any oneOf types. There's an open issue for openapiv3 support in grpc-gateway (houses protoc-gen-swagger as well grpc-ecosystem/grpc-gateway#441)

@krishna-birla They need some help getting it done, but someone did make a start. Might be our best bet....

@krishna-birla
Copy link
Author

@zwiedmann-isp
I am more than willing to contribute towards this effort.

@javidang
Copy link

@krishna-birla My team is also looking for the same and we've found 2 more alternatives for evaluation so far:

Hope these help.

hi @balnice . were you able to use openapi-generator for openAPI v3 generation? we currently use similar grpc-bridge that takes care of swagger generation during runtime, it seems like openapi-generator is more of "do it yourself" style approach to the problem.

@balnice
Copy link

balnice commented Apr 8, 2021

No idea what you mean by "do it yourself". If you need help with openapi-generator, simply open an issue in that repo.

@johnwayne19860314
Copy link

@krishna-birla My team is also looking for the same and we've found 2 more alternatives for evaluation so far:

Hope these help.

hi @balnice . were you able to use openapi-generator for openAPI v3 generation? we currently use similar grpc-bridge that takes care of swagger generation during runtime, it seems like openapi-generator is more of "do it yourself" style approach to the problem.

could this grpc-bridge generate the openapiv3 and solve the problem with oneof?

@javidang
Copy link

javidang commented Jul 7, 2022

@krishna-birla My team is also looking for the same and we've found 2 more alternatives for evaluation so far:

Hope these help.

hi @balnice . were you able to use openapi-generator for openAPI v3 generation? we currently use similar grpc-bridge that takes care of swagger generation during runtime, it seems like openapi-generator is more of "do it yourself" style approach to the problem.

could this grpc-bridge generate the openapiv3 and solve the problem with oneof?

nope, that is why I was looking into openapi-generator. We ended up moving away from automatic swagger generation at the end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants