swag
swag copied to clipboard
Support `null` Package and Data-Types
Describe the bug
swag init
fails when compiling models which contain structs from the gopkg.in/guregu/null.v4
package.
To Reproduce
I have a PATCH
endpoint where every field is optional, so my struct looks like this:
import "gopkg.in/guregu/null.v4"
type Request struct {
Email null.String
IsAdmin null.Bool
}
Having marked up my endpoint like so:
// UserUpdateHandler godoc
// ...
// @Param user body models.Request true "Updated user data."
// ...
When I run swag init
, it chokes on items in the gopkg.in/guregu/null.v4
package:
2021/08/25 15:50:45 ParseComment error in file pkg/routes/sadmin/users/root.go :cannot find type definition: null.Bool
Expected behavior
I expected for swag
to understand that null.*
are simply nullable types.
Screenshots If applicable, add screenshots to help explain your problem.
Your swag version
1.7.1
Your go version
go version go1.16.6 linux/amd64
Desktop (please complete the following information):
- OS: elementary OS Loki (Ubuntu 16.04 LTS) amd64
Additional context
If I shouldn't be using the null.*
times for optional values in models, what should I be using?
Try instead of
import "gopkg.in/guregu/null.v4"
type Request struct {
Email null.String
IsAdmin null.Bool
}
this one
import null "gopkg.in/guregu/null.v4"
type Request struct {
Email null.String
IsAdmin null.Bool
}
@naftulikay, have you figured it out?
@SmartPhoneJava why would changing the imported package name work? Is there some logic within swaggo that will understand it if I force the package name? The code above does compile.
@ubogdan I haven't tested this yet because I don't see how it would work differently. I'll attempt it at some point. Can you link to code or documentation that covers how this works?
@naftulikay If the suggested workaround works it means there is an issue in the swag parser related to strings.Split
.
Swagger is Open Source. Feel free to look at the source code.
Please test and let us know.
@naftulikay swaggo has different strategies to parse named and unnamed imports for detecting imported types.
You can see it in https://github.com/swaggo/swag/blob/master/packages.go#L245
I have an assumption that in the case of an unnamed import, swaggo uses the part after the slash as the package name. For gopkg.in/guregu/null.v4
it is null.v4
. Accordingly, instead of null.String
, swaggo expects null.v4.String
, which is incorrect.
Check whether the import naming will work and everything will become clear :)
I tried it out, and no dice:
pkg/routes/login/root.go:
package login
import (
// ...
null "gopkg.in/guregu/null.v4"
)
// LoginHandler godoc
// @Summary Login
// @Tags auth
// @Description Log a user in using email and password.
// @Accept json
// @Param login body views.LoginRequest true "Login Credentials"
// @Produce json
// @Success 200 {object} views.Response{data=views.LoginResponse}
// @Failure 400 {object} views.Response
// @Failure 403 {object} views.Response
// @Router /login [post]
func LoginHandler(w http.ResponsWriter, r *http.Request) {
// ...
resp := views.LoginRequest {
// ...
}
if err := json.NewEncoder(w).Encode(resp); err != nil {
// ...
}
}
pkg/views/root.go:
package views
import (
// ...
null "gopkg.in/guregu/null.v4"
)
type Response struct {
StatusCode uint16 `json:"status_code"`
Error null.String `json:"error"`
Data interface{} `json:"data"`
Links ResponseLinks `json:"_links"`
}
type ResponseLinks struct {
Self string `json:"_self"`
Prev null.String `json:"_prev,omitempty"`
Next null.String `json:"_next,omitempty"`
}
If I add swaggertype:"string"
to each of the null.String
fields, it does, in fact, work.
@ubogdan @SmartPhoneJava is there anything else I should try?
@naftulikay Thanks for letting us know about the issue.
A quick dirty workaround is to use "swaggertype" to override the value with a primitive as you described above.
@ubogdan Is there a swagger struct field tag that I can use to mark a struct field as optional? I'm using swaggertype:"string"
for my null.String
values, but is there a way that I can inform the user that this is an optional value and does not need to be included?
@ubogdan ping on this: is there a tag that I can use to let Swagger know the field can be null?
You can use validate:"required"
to signal that field is not optional :).
Is there a validate: "not-required"
to signal that a field is indeed optional? Right now with swaggertype:"string"
it shows all fields as required when any null.*
type should be optional.
Hi, I am getting those structs from https://github.com/volatiletech/sqlboiler, so I cannot really add those tags or the way it imports null. Is there a solution to this?
Hello, I also meet a similar problem, and here is my code:
// api comment
// @Param data body api.Problem true "comment"
import "mime/multipart"
type Problem struct {
Input *multipart.FileHeader `form:"input"`
Output *multipart.FileHeader `form:"output"`
}
And when I run swag init
, the error occurs:
ParseComment error in file :cannot find type definition: multipart.FileHeader
So the only solution now is to use swaggertype
or swaggerignore
?