Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion creating swagger.json file from proto file

I've created a proto file with all the necessary messages and rpc functions for a REST webservice I intend to generate. Using the protoc-gen-swagger plugin I've managed to compile that proto file into a swagger.json file and all seems well, except for two things, which I can't seem to work out.

  1. All the definitions in the swagger.json file has the name of my proto file's package prefixed onto them. Is there a way to get rid of this?

  2. All of the fields of my messages are "optional". They're not specified explicitly as such but they're not specified to be "required" which, by definition, makes them optional. Proto3 no longer supports required/optional/repeating but even if I use Proto2 and add those keywords, it doesn't seem to affect the swagger.json ouput. How do I specifiy in my proto file that a field is required such that protoc-gen-swagger will add the required section to the json output?

Here is a sample of a very basic proto file:

webservice.proto

syntax = "proto3";
package mypackage;
import "google/api/annotations.proto";

service MyAPIWebService {
    rpc MyFunc (MyMessage) returns (MyResponse) {
        option (google.api.http) = {
            post: "/message"
            body: "*"
        };
    }
}

message MyMessage {
    string MyString = 1;
    int64 MyInt = 2;
}

message MyResponse {
    string MyString = 1;
}

This is then compiled into a swagger.json file with the following command:

protoc -I. -I"%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis" --swagger_out=logtostderr=true:. webservice.proto

which yields the following output: webservice.swagger.json

{
  "swagger": "2.0",
  "info": {
    "title": "webservice.proto",
    "version": "version not set"
  },
  "schemes": [
    "http",
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/message": {
      "post": {
        "operationId": "MyFunc",
        "responses": {
          "200": {
            "description": "",
            "schema": {
              "$ref": "#/definitions/mypackageMyResponse"
            }
          }
        },
        "parameters": [
          {
            "name": "body",
            "in": "body",
            "required": true,
            "schema": {
              "$ref": "#/definitions/mypackageMyMessage"
            }
          }
        ],
        "tags": [
          "MyAPIWebService"
        ]
      }
    }
  },
  "definitions": {
    "mypackageMyMessage": {
      "type": "object",
      "properties": {
        "MyString": {
          "type": "string"
        },
        "MyInt": {
          "type": "string",
          "format": "int64"
        }
      }
    },
    "mypackageMyResponse": {
      "type": "object",
      "properties": {
        "MyString": {
          "type": "string"
        }
      }
    }
  }
}
  1. Notice how MyMessage and MyResponse in the proto file translates to mypackageMyMessage and mypackageMyResponse in the json file.

  2. If I wanted, for instance, MyMessage:MyString to be required, I'd have to add a section to the "mypackageMyMessage" section in "definitions" that looks like this:

    "required":[ "MyString" ]

I would definitely prefer if there was a way I could specify that in the proto file already so that I don't have to manually edit the json file every time I compile it.

like image 285
Dewald Swanepoel Avatar asked Feb 21 '17 13:02

Dewald Swanepoel


2 Answers

Posting here for anyone else who comes across this question looking for the same information.


UPDATE This is where the code defines how definitions are created.

https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-swagger/genswagger/template.go#L859


This is how you can denote fields as required -- add a custom option to your message definition:

message MyMessage {
    option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
        json_schema: {
            title: "MyMessage"
            description: "Does something neat"
            required: ["MyString"]
        }
    };

    string MyString = 1;
    int64 MyInt = 2;
}
like image 193
Jodie Putrino Avatar answered Oct 02 '22 15:10

Jodie Putrino


Your prefix mypackage is a part of namespacing in .proto file. It is coming from line: package mypackage; delete this line and regenerate json

like image 24
Pavel Avatar answered Oct 02 '22 16:10

Pavel