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

OpenAPI doesn't support the semantics of protobuf.oneof so we can't describe it at the moment #822

Open
alexandrucosminmihai opened this issue Aug 12, 2020 · 0 comments

Comments

@alexandrucosminmihai
Copy link
Collaborator

(Note: I use oneOf, anyOf, allOf (camel-case) to refer to OpenAPI's keywords and protobuf.oneof to refer to protobuf's.)

After more thorough investigation and experimentation I figured out that at the moment there is no way to correctly describe protobuf.oneof’s behaviour using the OpenAPI Specification.

The first big problem is related to route parameters descriptions in OpenAPI. OpenAPI does not allow interdependence between parameters (including mutual exclusion which is the core semantic of protobuf.oneof). Therefore, there is no way to describe the behavior of protobuf.oneof when used to describe a route parameter, because the best we could do with OpenAPI is describe a single parameter with a single name (field_oneof1, for example) that accepts anyOf the schemas of the fields that are part of the protobuf.oneof. This is not correct because the protobuf.oneof does not define a field with multiple possible types, but rather it defines a mutual exclusion between multiple fields, each with their own name and type, so this OpenAPI solution would fail to describe the API correctly (i.e. instead of specifying that a method expects either a field_one argument of type int32, or a field_two argument of type string, the OpenAPI description would specify that the API method expects an argument field_oneof which can be either of type int32 or string). Therefore, defining the protobuf.oneof semantic for method arguments with OpenAPI is impossible at the moment, but what about response types?

The OpenAPI Specification offers the special operators oneOf, anyOf, allOf which can be used to describe a schema by combining other schemas in the following ways:

  • “this schema should respect exactly oneOf the following schemas”,
  • “this schema should respect at least a schema of anyOf of the following schemas”,
  • “this schema should respect allOf the the following schemas (i.e. this schema is a merge of all the following schemas)”.

So the idea I had, was that, at least for result types of API methods, we could describe the protobuf message schema correctly using anyOf&allOf in the following way: use allOf to combine the static fields of the protobuf message with the protobuf.oneof fields that have different options. For each protobuf.oneof field, define an anyOf that holds exactly one OpenAPI object schema for each inner field of a protobuf.oneof field. This OpenAPI object schema has exactly one field with the name of the protobuf.oneof inner field and its type description. This is a hacky approach, but it seems to work with the popular ReDoc documentation generation tool, but with a big caveat: if there are two protobuf.oneof fields that are described using this approach, only the first one that is described will be displayed.

A second solution for describing the protobuf.oneofs that are part of result type messages, would be to describe a separate message for each protobuf.oneofs fields combination and describe the result type message schema as an OpenAPI oneOf of all the possible messages. This solution implies generating a number equal to the cardinal of the Cartesian product of all the sets that represent the inner fields of all protobuf.oneofs that are part of the result type protobuf message, which can be a relatively large number of type schemas to display in the documentation and it would require a (confusing/impractical) naming convention for the generated combination types.

Therefore, there is no way to practically describe the protobuf.oneof using OpenAPI, neither for parameter types, nor for result types.

The current “compromise” solution that I'm developing is to define all the inner protobuf.oneofs’ fields as standalone parameters or top-level message fields and add a comment describing the fact that they are part of a protobuf.oneof and only one of them should be chosen per protobuf.oneof.

If in the future the OpenAPI Specification allows to describe the desired behavior, support for it should be implemented in the OpenAPI description generation code.

@alexandrucosminmihai alexandrucosminmihai changed the title OpenAPI doesn't support the semantics of protobuf.oneof so we can't implement it at the moment OpenAPI doesn't support the semantics of protobuf.oneof so we can't describe it at the moment Aug 12, 2020
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

1 participant