swaggo / swag

Automatically generate RESTful API documentation with Swagger 2.0 for Go.
MIT License
10.47k stars 1.19k forks source link

support for function scoped struct in type method #1649

Open win-arturo opened 1 year ago

win-arturo commented 1 year ago

Is your feature request related to a problem? Please describe. Using the gin framework, we have the handlers generally defined in a "service struct". The handlers often define their own input and output structs. The current function scoped struct support does not handle this case.

package bob

type service struct {}

// @Success 200 {object} bob.service.handleARequest.output "object containing the A"
func (s *service) handleARequest(ctx *gin.context) {
          type input struct {}
          type output struct {A int}
          c.JSON(http.StatusOK, output{A:5}
}

Describe the solution you'd like Extend the function scoped struct feature to support methods of a type.\ Describe alternatives you've considered Pulling the struct out of the method works but is not the desired solution.

Additional context If this is desirable, I can probably add it.

supengchuan commented 1 year ago

This feature is urgently needed

svennjegac commented 10 months ago

Afaik, bob.handleARequest.output should work. (It is working for me, I am using branch v2, generation openAPISpec 3.1.0).

Yes, struct name is omitted, which I don't like because of possible collisions, but it is working ok for me.

win-arturo commented 10 months ago

@svennjegac does it work on the non-v2 branch?

I'm using

swag --version
swag version v1.16.2
win-arturo commented 10 months ago

Doesn't work here:

2023/10/25 12:31:03 ParseComment error in file <redacted>/service.go :cannot find type definition: serviceStruct.serviceStructMethod.serviceStructMethodType
internal/swagger/main-info.go:3: running "swag": exit status 1

Adding the package name (e.g. pkg1.serviceStruct.serviceStructMethod.serviceStructMethodType) allows swag to complete successfully but the swagger generated isn't useful:

-                            "$ref": "#/definitions/pkg1.serviceStructMethodType"
+                            "$ref": "#/definitions/pkg1.serviceStruct"
win-arturo commented 7 months ago

$ swag --version swag version v1.16.2

this works:

package testbed

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

type service struct{}

// @Success 200 {object} testbed.handleARequest.output "object containing the A"
func (s service) handleARequest(c *gin.Context) {
    type input struct{}
    type output struct{ A int }
    c.JSON(http.StatusOK, output{A: 5})
}

// @Success 200 {object} testbed.handleBRequest.output "object containing the A"
func (s service) handleBRequest(c *gin.Context) {
    type input struct{}
    type output struct{ B int }
    c.JSON(http.StatusOK, output{B: 5})
}

Updated swagger:

+        "testbed.handleARequest.output": {
+            "type": "object",
+            "properties": {
+                "a": {
+                    "type": "integer"
+                }
+            }
+        },
+        "testbed.handleBRequest.output": {
+            "type": "object",
+            "properties": {
+                "b": {
+                    "type": "integer"
+                }
+            }
+        },

Multiple service structs with same name and objects does not. Generates the same swagger as the above without returning an error.

Probably can live with that

package testbed

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

type service struct{}

// @Success 200 {object} testbed.handleARequest.output "object containing the A"
func (s service) handleARequest(c *gin.Context) {
    type input struct{}
    type output struct{ A int }
    c.JSON(http.StatusOK, output{A: 5})
}

// @Success 200 {object} testbed.handleBRequest.output "object containing the A"
func (s service) handleBRequest(c *gin.Context) {
    type input struct{}
    type output struct{ B int }
    c.JSON(http.StatusOK, output{B: 5})
}

type serviceN struct{}

// @Success 200 {object} testbed.handleARequest.output "object containing the A"
func (s serviceN) handleARequest(c *gin.Context) {
    type input struct{}
    type output struct{ A string }
    c.JSON(http.StatusOK, output{A: "5"})
}