You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(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.
The text was updated successfully, but these errors were encountered:
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
(Note: I use
oneOf
,anyOf
,allOf
(camel-case) to refer to OpenAPI's keywords andprotobuf.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 ofprotobuf.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 acceptsanyOf
the schemas of the fields that are part of theprotobuf.oneof
. This is not correct because theprotobuf.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 afield_one
argument of typeint32
, or afield_two
argument of typestring
, the OpenAPI description would specify that the API method expects an argumentfield_oneof
which can be either of typeint32
orstring
). Therefore, defining theprotobuf.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:oneOf
the following schemas”,anyOf
of the following schemas”,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: useallOf
to combine the static fields of the protobuf message with theprotobuf.oneof
fields that have different options. For eachprotobuf.oneof
field, define ananyOf
that holds exactly one OpenAPI object schema for each inner field of aprotobuf.oneof
field. This OpenAPI object schema has exactly one field with the name of theprotobuf.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 twoprotobuf.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.oneof
s that are part of result type messages, would be to describe a separate message for eachprotobuf.oneof
s fields combination and describe the result type message schema as an OpenAPIoneOf
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 allprotobuf.oneof
s 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.oneof
s’ fields as standalone parameters or top-level message fields and add a comment describing the fact that they are part of aprotobuf.oneof
and only one of them should be chosen perprotobuf.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.
The text was updated successfully, but these errors were encountered: