optimized
This commit is contained in:
parent
ce24620329
commit
d06684494a
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
func Generator(ctx *cli.Context) error {
|
func Generator(ctx *cli.Context) error {
|
||||||
pkg := ctx.String("package")
|
pkg := ctx.String("package")
|
||||||
|
fileName := ctx.String("filename")
|
||||||
std, err := ioutil.ReadAll(os.Stdin)
|
std, err := ioutil.ReadAll(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -17,7 +18,11 @@ func Generator(ctx *cli.Context) error {
|
|||||||
|
|
||||||
var plugin generate.Plugin
|
var plugin generate.Plugin
|
||||||
plugin.ParentPackage = pkg
|
plugin.ParentPackage = pkg
|
||||||
|
plugin.FileName = fileName
|
||||||
|
|
||||||
|
if len(plugin.FileName) == 0 {
|
||||||
|
plugin.FileName = "rest.swagger.json"
|
||||||
|
}
|
||||||
err = json.Unmarshal(std, &plugin)
|
err = json.Unmarshal(std, &plugin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
package example
|
package example
|
||||||
|
|
||||||
//go:generate goctl api plugin -plugin goctl-swagger="swagger" -api user.api -dir .
|
//go:generate goctl api plugin -plugin goctl-swagger="swagger -filename user.json" -api user.api -dir .
|
||||||
|
@ -14,13 +14,13 @@ type (
|
|||||||
}
|
}
|
||||||
// 登录请求
|
// 登录请求
|
||||||
LoginReq {
|
LoginReq {
|
||||||
// 用户名
|
|
||||||
Username string `json:"username" desc:"用户名"`
|
Username string `json:"username" desc:"用户名"`
|
||||||
Password string `json:"password"` //密码
|
Password string `json:"password"` //密码
|
||||||
} // 登录请求
|
} // 登录请求
|
||||||
|
|
||||||
UserInfoReq {
|
UserInfoReq {
|
||||||
Id string `path:"id"`
|
Id string `path:"id"` // 会员ID
|
||||||
|
Page string `form:"page,default=1"` //分页
|
||||||
}
|
}
|
||||||
|
|
||||||
UserInfoReply {
|
UserInfoReply {
|
||||||
@ -36,7 +36,8 @@ type (
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserSearchReply {
|
UserSearchReply {
|
||||||
KeyWord []UserInfoReply
|
KeyWord []*UserInfoReply
|
||||||
|
KeyWords []*UserSearchReq
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ type (
|
|||||||
Style string
|
Style string
|
||||||
Dir string
|
Dir string
|
||||||
ParentPackage string
|
ParentPackage string
|
||||||
|
FileName string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,6 +25,9 @@ var (
|
|||||||
"int32": reflect.Int,
|
"int32": reflect.Int,
|
||||||
"int64": reflect.Int64,
|
"int64": reflect.Int64,
|
||||||
"[]string": reflect.Slice,
|
"[]string": reflect.Slice,
|
||||||
|
"[]int": reflect.Slice,
|
||||||
|
"[]int64": reflect.Slice,
|
||||||
|
"[]int32": reflect.Slice,
|
||||||
"bool": reflect.Bool,
|
"bool": reflect.Bool,
|
||||||
"struct": reflect.Struct,
|
"struct": reflect.Struct,
|
||||||
}
|
}
|
||||||
@ -153,7 +157,6 @@ type schemaCore struct {
|
|||||||
Example json.RawMessage `json:"example,omitempty"`
|
Example json.RawMessage `json:"example,omitempty"`
|
||||||
|
|
||||||
Items *swaggerItemsObject `json:"items,omitempty"`
|
Items *swaggerItemsObject `json:"items,omitempty"`
|
||||||
|
|
||||||
// If the item is an enumeration include a list of all the *NAMES* of the
|
// If the item is an enumeration include a list of all the *NAMES* of the
|
||||||
// enum values. I'm not sure how well this will work but assuming all enums
|
// enum values. I'm not sure how well this will work but assuming all enums
|
||||||
// start from 0 index it will be great. I don't think that is a good assumption.
|
// start from 0 index it will be great. I don't think that is a good assumption.
|
||||||
|
@ -21,7 +21,7 @@ func Do(in Plugin) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output := in.Dir + "/rest.swagger.json"
|
output := in.Dir + "/" + in.FileName
|
||||||
|
|
||||||
err = ioutil.WriteFile(output, formatted.Bytes(), 0666)
|
err = ioutil.WriteFile(output, formatted.Bytes(), 0666)
|
||||||
|
|
||||||
|
@ -15,6 +15,16 @@ var (
|
|||||||
strColon = []byte(":")
|
strColon = []byte(":")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultOption = "default"
|
||||||
|
stringOption = "string"
|
||||||
|
optionalOption = "optional"
|
||||||
|
optionsOption = "options"
|
||||||
|
rangeOption = "range"
|
||||||
|
optionSeparator = "|"
|
||||||
|
equalToken = "="
|
||||||
|
)
|
||||||
|
|
||||||
func applyGenerate(p Plugin) (*swaggerObject, error) {
|
func applyGenerate(p Plugin) (*swaggerObject, error) {
|
||||||
|
|
||||||
s := swaggerObject{
|
s := swaggerObject{
|
||||||
@ -43,6 +53,7 @@ func applyGenerate(p Plugin) (*swaggerObject, error) {
|
|||||||
renderServiceRoutes(p.Api.Service, p.Api.Service.Groups, s.Paths, requestResponseRefs)
|
renderServiceRoutes(p.Api.Service, p.Api.Service.Groups, s.Paths, requestResponseRefs)
|
||||||
m := messageMap{}
|
m := messageMap{}
|
||||||
renderReplyAsDefinition(s.Definitions, m, p.Api.Types, requestResponseRefs)
|
renderReplyAsDefinition(s.Definitions, m, p.Api.Types, requestResponseRefs)
|
||||||
|
|
||||||
return &s, nil
|
return &s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,19 +81,54 @@ func renderServiceRoutes(service spec.Service, groups []spec.Group, paths swagge
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reqRef := fmt.Sprintf("#/definitions/%s", route.RequestType.Name)
|
if strings.ToUpper(route.Method) == http.MethodGet {
|
||||||
if len(route.RequestType.Name) > 0 {
|
for _, member := range route.RequestType.Members {
|
||||||
var schema = swaggerSchemaObject{
|
if strings.Contains(member.Tag, "path") {
|
||||||
schemaCore: schemaCore{
|
continue
|
||||||
Ref: reqRef,
|
}
|
||||||
},
|
tempKind := swaggerMapTypes[strings.Replace(member.Type, "[]", "", -1)]
|
||||||
|
ftype, format, ok := primitiveSchema(tempKind, member.Type)
|
||||||
|
if !ok {
|
||||||
|
ftype = tempKind.String()
|
||||||
|
format = "UNKNOWN"
|
||||||
|
}
|
||||||
|
sp := swaggerParameterObject{In: "query", Type: ftype, Format: format}
|
||||||
|
|
||||||
|
for _, tag := range member.Tags() {
|
||||||
|
sp.Name = tag.Name
|
||||||
|
if len(tag.Options) == 0 {
|
||||||
|
sp.Required = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, option := range tag.Options {
|
||||||
|
if strings.HasPrefix(option, defaultOption) {
|
||||||
|
segs := strings.Split(option, equalToken)
|
||||||
|
if len(segs) == 2 {
|
||||||
|
sp.Default = segs[1]
|
||||||
|
}
|
||||||
|
} else if !strings.HasPrefix(option, optionalOption) {
|
||||||
|
sp.Required = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parameters = append(parameters, sp)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
reqRef := fmt.Sprintf("#/definitions/%s", route.RequestType.Name)
|
||||||
|
if len(route.RequestType.Name) > 0 {
|
||||||
|
var schema = swaggerSchemaObject{
|
||||||
|
schemaCore: schemaCore{
|
||||||
|
Ref: reqRef,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
parameters = append(parameters, swaggerParameterObject{
|
||||||
|
Name: "body",
|
||||||
|
In: "body",
|
||||||
|
Required: true,
|
||||||
|
Schema: &schema,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
parameters = append(parameters, swaggerParameterObject{
|
|
||||||
Name: "body",
|
|
||||||
In: "body",
|
|
||||||
Required: true,
|
|
||||||
Schema: &schema,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pathItemObject, ok := paths[path]
|
pathItemObject, ok := paths[path]
|
||||||
@ -172,7 +218,25 @@ func renderReplyAsDefinition(d swaggerDefinitionsObject, m messageMap, p []spec.
|
|||||||
schema.Properties = &swaggerSchemaObjectProperties{}
|
schema.Properties = &swaggerSchemaObjectProperties{}
|
||||||
}
|
}
|
||||||
*schema.Properties = append(*schema.Properties, kv)
|
*schema.Properties = append(*schema.Properties, kv)
|
||||||
|
|
||||||
|
for _, tag := range member.Tags() {
|
||||||
|
if len(tag.Options) == 0 {
|
||||||
|
schema.Required = append(schema.Required, tag.Name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, option := range tag.Options {
|
||||||
|
switch {
|
||||||
|
case !strings.HasPrefix(option, optionalOption):
|
||||||
|
if !contains(schema.Required, tag.Name) {
|
||||||
|
schema.Required = append(schema.Required, tag.Name)
|
||||||
|
}
|
||||||
|
case strings.HasPrefix(option, defaultOption):
|
||||||
|
case strings.HasPrefix(option, optionsOption):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d[i2.Name] = schema
|
d[i2.Name] = schema
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,18 +246,32 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
|
|||||||
ret := swaggerSchemaObject{}
|
ret := swaggerSchemaObject{}
|
||||||
|
|
||||||
var core schemaCore
|
var core schemaCore
|
||||||
|
//spew.Dump(member)
|
||||||
kind := swaggerMapTypes[member.Type]
|
kind := swaggerMapTypes[member.Type]
|
||||||
var props *swaggerSchemaObjectProperties
|
var props *swaggerSchemaObjectProperties
|
||||||
|
|
||||||
|
comment := member.GetComment()
|
||||||
|
comment = strings.Replace(comment, "//", "", -1)
|
||||||
|
|
||||||
switch ft := kind; ft {
|
switch ft := kind; ft {
|
||||||
case reflect.Invalid: //[]Struct 也有可能是 Struct
|
case reflect.Invalid: //[]Struct 也有可能是 Struct
|
||||||
// []Struct
|
// []Struct
|
||||||
|
//map[ArrayType:map[Star:map[StringExpr:UserSearchReq] StringExpr:*UserSearchReq] StringExpr:[]*UserSearchReq]
|
||||||
refTypeName := strings.Replace(member.Type, "[", "", 1)
|
refTypeName := strings.Replace(member.Type, "[", "", 1)
|
||||||
refTypeName = strings.Replace(refTypeName, "]", "", 1)
|
refTypeName = strings.Replace(refTypeName, "]", "", 1)
|
||||||
|
refTypeName = strings.Replace(refTypeName, "*", "", 1)
|
||||||
core = schemaCore{
|
core = schemaCore{
|
||||||
Ref: "#/definitions/" + refTypeName,
|
Ref: "#/definitions/" + refTypeName,
|
||||||
}
|
}
|
||||||
|
case reflect.Slice:
|
||||||
|
tempKind := swaggerMapTypes[strings.Replace(member.Type, "[]", "", -1)]
|
||||||
|
ftype, format, ok := primitiveSchema(tempKind, member.Type)
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
core = schemaCore{Type: ftype, Format: format}
|
||||||
|
} else {
|
||||||
|
core = schemaCore{Type: ft.String(), Format: "UNKNOWN"}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
ftype, format, ok := primitiveSchema(ft, member.Type)
|
ftype, format, ok := primitiveSchema(ft, member.Type)
|
||||||
if ok {
|
if ok {
|
||||||
@ -221,7 +299,6 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ret = swaggerSchemaObject{
|
ret = swaggerSchemaObject{
|
||||||
schemaCore: core,
|
schemaCore: core,
|
||||||
Properties: props,
|
Properties: props,
|
||||||
@ -233,6 +310,24 @@ func schemaOfField(member spec.Member) swaggerSchemaObject {
|
|||||||
Properties: props,
|
Properties: props,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ret.Description = comment
|
||||||
|
|
||||||
|
for _, tag := range member.Tags() {
|
||||||
|
if len(tag.Options) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, option := range tag.Options {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(option, defaultOption):
|
||||||
|
segs := strings.Split(option, equalToken)
|
||||||
|
if len(segs) == 2 {
|
||||||
|
ret.Default = segs[1]
|
||||||
|
}
|
||||||
|
case strings.HasPrefix(option, optionsOption):
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -271,3 +366,12 @@ func countParams(path string) uint16 {
|
|||||||
n += uint16(bytes.Count(s, strColon))
|
n += uint16(bytes.Count(s, strColon))
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
func contains(s []string, str string) bool {
|
||||||
|
for _, v := range s {
|
||||||
|
if v == str {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
2
go.sum
2
go.sum
@ -250,7 +250,9 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU=
|
||||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
7
main.go
7
main.go
@ -15,7 +15,12 @@ var (
|
|||||||
Name: "swagger",
|
Name: "swagger",
|
||||||
Usage: "generates swagger.json",
|
Usage: "generates swagger.json",
|
||||||
Action: action.Generator,
|
Action: action.Generator,
|
||||||
Flags: []cli.Flag{},
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "filename",
|
||||||
|
Usage: "swagger save file name",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user