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

Add optional_nullable option (default: off) to mark Proto3 Optional fields as x-nullable #2215

Merged
merged 3 commits into from
Jul 2, 2021
Merged

Conversation

irridia
Copy link
Contributor

@irridia irridia commented Jul 1, 2021

See #669 for more background.

This change adds an optional (default: off) proto3_optional_nullable flag to protoc-gen-openapiv2 that will mark Proto3 fields marked with the optional label as x-nullable. The OAS specification calls this out as nullable, but this behavior has been "back-ported" to OAS2 using the System Extension x-nullable.

The effect of the Proto3 Optional flag on the GRPC is exactly this—it sets primitive types to pointers. It's certainly open to debate why we have Proto2 optional, the optional field descriptor, and Proto3 optional, but fundamentally Proto3 Optional is designed to solve the "true presence" issue as discussed in #669, at least IMHO. Whereas the other options never felt specific to this nullable behavior. Proto3 optional field presence discussion is here.

It could be a valid approach to make this behavior the default, but for now it felt best to me to retain backwards compatibility until the semantics are well understood.

Potentially:
Fixes #669

Adds:

  • proto3_optional_nullable command line flag.
  • If proto3_optional_nullable is set, and the proto field has proto3optional set, the schema XNullable state is set to true, which emits the OAPI x-nullable tag.

Comments and feedback welcome! @johanbrandhorst

@google-cla google-cla bot added the cla: yes label Jul 1, 2021
Copy link
Collaborator

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great, just some nits on the naming and style!

@@ -278,6 +283,11 @@ protoc_gen_openapiv2 = rule(
doc = "whether to remove the service prefix in the operationID" +
" generation. Can introduce duplicate operationIDs, use with caution.",
),
"optional_nullable": attr.bool(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: naming

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated!

Comment on lines 90 to 91
// optionalNullable specifies whether Proto3 Optional fields should be marked as x-nullable.
optionalNullable bool
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we name this field and related helpers proto3OptionalNullable to make it more explicit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, done. I was debating this myself.

Type string `json:"type,omitempty"`
Format string `json:"format,omitempty"`
Ref string `json:"$ref,omitempty"`
Nullable bool `json:"x-nullable,omitempty"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x-nullable isn't defined in the referenced docs (http://swagger.io/specification/#itemsObject), could you please add a reference here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated that URL to point to the v2 specification, and added a reference to the v3 spec that calls out nullable. x-nullable is a "back-ported" extension to emulate this v3 behavior in v2, but it's more of a widely used convention than part of any formal spec. I've added what I think is helpful; let me know if it's too much or missing something you'd want to see/know.

@@ -581,6 +582,10 @@ func schemaOfField(f *descriptor.Field, reg *descriptor.Registry, refs refMap) o
updateSwaggerObjectFromFieldBehavior(&ret, j, f)
}

if reg.GetOptionalNullable() && f.Proto3Optional != nil && *f.Proto3Optional {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we just use the getter?

Suggested change
if reg.GetOptionalNullable() && f.Proto3Optional != nil && *f.Proto3Optional {
if reg.GetOptionalNullable() && f.GetProto3Optional() {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I was using completion and missed the presence of the getters. Updated.

@johanbrandhorst
Copy link
Collaborator

Looks like there's a syntax error in the bazel definitions?

./protoc-gen-openapiv2/defs.bzl:291:32: syntax error near "openapi_configuration"
./protoc-gen-openapiv2/defs.bzl # reformat

@irridia
Copy link
Contributor Author

irridia commented Jul 2, 2021

Looks like there's a syntax error in the bazel definitions?

./protoc-gen-openapiv2/defs.bzl:291:32: syntax error near "openapi_configuration"
./protoc-gen-openapiv2/defs.bzl # reformat

Fixed, I had a missing comma. I didn't have access to the CircleCI to see the details of why the test failed.

Copy link
Collaborator

@johanbrandhorst johanbrandhorst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes, LGTM!

@johanbrandhorst johanbrandhorst merged commit 42c494f into grpc-ecosystem:master Jul 2, 2021
@irridia
Copy link
Contributor Author

irridia commented Jul 2, 2021

Thanks so much for the time, @johanbrandhorst !

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

Successfully merging this pull request may close these issues.

protoc-gen-swagger: should well known types be nullable
2 participants