diff --git a/contrib/drivers/clickhouse/clickhouse.go b/contrib/drivers/clickhouse/clickhouse.go index 966130a56..75f84f5c1 100644 --- a/contrib/drivers/clickhouse/clickhouse.go +++ b/contrib/drivers/clickhouse/clickhouse.go @@ -25,6 +25,7 @@ import ( "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gutil" "github.com/google/uuid" "github.com/shopspring/decimal" @@ -49,7 +50,7 @@ const ( filterTypePattern = `(?i)^UPDATE|DELETE` replaceSchemaPattern = `@(.+?)/([\w\.\-]+)+` needParsedSqlInCtx gctx.StrKey = "NeedParsedSql" - OrmTagForStruct = "orm" + OrmTagForStruct = gtag.ORM driverName = "clickhouse" ) diff --git a/net/gclient/gclient_request_obj.go b/net/gclient/gclient_request_obj.go index d7dc2b097..45e65c4cc 100644 --- a/net/gclient/gclient_request_obj.go +++ b/net/gclient/gclient_request_obj.go @@ -13,11 +13,11 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" - "github.com/gogf/gf/v2/net/goai" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gmeta" + "github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gutil" ) @@ -41,21 +41,21 @@ import ( // DoRequestObj(ctx, req, &res) func (c *Client) DoRequestObj(ctx context.Context, req, res interface{}) error { var ( - method = gmeta.Get(req, goai.TagNameMethod).String() - path = gmeta.Get(req, goai.TagNamePath).String() + method = gmeta.Get(req, gtag.Method).String() + path = gmeta.Get(req, gtag.Path).String() ) if method == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, `no "%s" tag found in request object: %s`, - goai.TagNameMethod, reflect.TypeOf(req).String(), + gtag.Method, reflect.TypeOf(req).String(), ) } if path == "" { return gerror.NewCodef( gcode.CodeInvalidParameter, `no "%s" tag found in request object: %s`, - goai.TagNamePath, reflect.TypeOf(req).String(), + gtag.Path, reflect.TypeOf(req).String(), ) } path = c.handlePathForObjRequest(path, req) diff --git a/net/ghttp/ghttp.go b/net/ghttp/ghttp.go index b9b79cfe1..de1808c08 100644 --- a/net/ghttp/ghttp.go +++ b/net/ghttp/ghttp.go @@ -12,6 +12,7 @@ import ( "reflect" "time" + "github.com/gogf/gf/v2/util/gtag" "github.com/gorilla/websocket" "github.com/gogf/gf/v2/container/gmap" @@ -180,7 +181,7 @@ var ( gracefulEnabled = false // defaultValueTags are the struct tag names for default value storing. - defaultValueTags = []string{"d", "default"} + defaultValueTags = []string{gtag.DefaultShort, gtag.Default} ) var ( diff --git a/net/ghttp/ghttp_server_router.go b/net/ghttp/ghttp_server_router.go index 9e6a98d54..752f75eb8 100644 --- a/net/ghttp/ghttp_server_router.go +++ b/net/ghttp/ghttp_server_router.go @@ -19,10 +19,10 @@ import ( "github.com/gogf/gf/v2/errors/gcode" "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/internal/consts" - "github.com/gogf/gf/v2/net/goai" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gmeta" + "github.com/gogf/gf/v2/util/gtag" ) var ( @@ -96,13 +96,13 @@ func (s *Server) setHandler(ctx context.Context, in setHandlerInput) { // Change the registered route according to meta info from its request structure. if handler.Info.Type != nil && handler.Info.Type.NumIn() == 2 { var objectReq = reflect.New(handler.Info.Type.In(1)) - if v := gmeta.Get(objectReq, goai.TagNamePath); !v.IsEmpty() { + if v := gmeta.Get(objectReq, gtag.Path); !v.IsEmpty() { uri = v.String() } - if v := gmeta.Get(objectReq, goai.TagNameMethod); !v.IsEmpty() { + if v := gmeta.Get(objectReq, gtag.Method); !v.IsEmpty() { method = v.String() } - if v := gmeta.Get(objectReq, goai.TagNameDomain); !v.IsEmpty() { + if v := gmeta.Get(objectReq, gtag.Domain); !v.IsEmpty() { domain = v.String() } } diff --git a/net/goai/goai.go b/net/goai/goai.go index 76d200dae..1fc8d74fd 100644 --- a/net/goai/goai.go +++ b/net/goai/goai.go @@ -19,6 +19,7 @@ import ( "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gtag" ) // OpenApiV3 is the structure defined from: @@ -36,18 +37,6 @@ type OpenApiV3 struct { ExternalDocs *ExternalDocs `json:"externalDocs,omitempty"` } -const ( - HttpMethodGet = `GET` - HttpMethodPut = `PUT` - HttpMethodPost = `POST` - HttpMethodDelete = `DELETE` - HttpMethodConnect = `CONNECT` - HttpMethodHead = `HEAD` - HttpMethodOptions = `OPTIONS` - HttpMethodPatch = `PATCH` - HttpMethodTrace = `TRACE` -) - const ( TypeInteger = `integer` TypeNumber = `number` @@ -72,15 +61,6 @@ const ( ParameterInCookie = `cookie` ) -const ( - TagNamePath = `path` - TagNameMethod = `method` - TagNameMime = `mime` - TagNameConsumes = `consumes` - TagNameType = `type` - TagNameDomain = `domain` -) - const ( validationRuleKeyForRequired = `required` validationRuleKeyForIn = `in:` @@ -90,14 +70,14 @@ var ( defaultReadContentTypes = []string{`application/json`} defaultWriteContentTypes = []string{`application/json`} shortTypeMapForTag = map[string]string{ - "d": "Default", - "sum": "Summary", - "sm": "Summary", - "des": "Description", - "dc": "Description", - "eg": "Example", - "egs": "Examples", - "ed": "ExternalDocs", + gtag.DefaultShort: gtag.Default, + gtag.SummaryShort: gtag.Summary, + gtag.SummaryShort2: gtag.Summary, + gtag.DescriptionShort: gtag.Description, + gtag.DescriptionShort2: gtag.Description, + gtag.ExampleShort: gtag.Example, + gtag.ExamplesShort: gtag.Examples, + gtag.ExternalDocsShort: gtag.ExternalDocs, } ) @@ -231,7 +211,7 @@ func (oai *OpenApiV3) golangTypeToSchemaName(t reflect.Type) string { return schemaName } -func (oai *OpenApiV3) fileMapWithShortTags(m map[string]string) map[string]string { +func (oai *OpenApiV3) fillMapWithShortTags(m map[string]string) map[string]string { for k, v := range shortTypeMapForTag { if m[v] == "" && m[k] != "" { m[v] = m[k] diff --git a/net/goai/goai_operation.go b/net/goai/goai_operation.go index db6e0b30d..42447db6f 100644 --- a/net/goai/goai_operation.go +++ b/net/goai/goai_operation.go @@ -30,7 +30,7 @@ type Operation struct { } func (oai *OpenApiV3) tagMapToOperation(tagMap map[string]string, operation *Operation) error { - var mergedTagMap = oai.fileMapWithShortTags(tagMap) + var mergedTagMap = oai.fillMapWithShortTags(tagMap) if err := gconv.Struct(mergedTagMap, operation); err != nil { return gerror.Wrap(err, `mapping struct tags to Operation failed`) } diff --git a/net/goai/goai_parameter.go b/net/goai/goai_parameter.go index d20e92cdc..6b6e122c5 100644 --- a/net/goai/goai_parameter.go +++ b/net/goai/goai_parameter.go @@ -32,7 +32,7 @@ type Parameter struct { } func (oai *OpenApiV3) tagMapToParameter(tagMap map[string]string, parameter *Parameter) error { - var mergedTagMap = oai.fileMapWithShortTags(tagMap) + var mergedTagMap = oai.fillMapWithShortTags(tagMap) if err := gconv.Struct(mergedTagMap, parameter); err != nil { return gerror.Wrap(err, `mapping struct tags to Parameter failed`) } diff --git a/net/goai/goai_parameter_ref.go b/net/goai/goai_parameter_ref.go index 433956788..4553fa52c 100644 --- a/net/goai/goai_parameter_ref.go +++ b/net/goai/goai_parameter_ref.go @@ -8,6 +8,7 @@ package goai import ( "fmt" + "net/http" "github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/errors/gcode" @@ -48,7 +49,7 @@ func (oai *OpenApiV3) newParameterRefWithStructMethod(field gstructs.Field, path } else { // Default the parameter input to "query" if method is "GET/DELETE". switch gstr.ToUpper(method) { - case HttpMethodGet, HttpMethodDelete: + case http.MethodGet, http.MethodDelete: parameter.In = ParameterInQuery default: diff --git a/net/goai/goai_path.go b/net/goai/goai_path.go index 37086e7e4..0d5f02a87 100644 --- a/net/goai/goai_path.go +++ b/net/goai/goai_path.go @@ -7,6 +7,7 @@ package goai import ( + "net/http" "reflect" "github.com/gogf/gf/v2/container/garray" @@ -17,6 +18,7 @@ import ( "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gmeta" + "github.com/gogf/gf/v2/util/gtag" ) type Path struct { @@ -97,7 +99,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { ) // Path check. if in.Path == "" { - in.Path = gmeta.Get(inputObject.Interface(), TagNamePath).String() + in.Path = gmeta.Get(inputObject.Interface(), gtag.Path).String() if in.Prefix != "" { in.Path = gstr.TrimRight(in.Prefix, "/") + "/" + gstr.TrimLeft(in.Path, "/") } @@ -106,7 +108,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { return gerror.NewCodef( gcode.CodeMissingParameter, `missing necessary path parameter "%s" for input struct "%s", missing tag in attribute Meta?`, - TagNamePath, inputStructTypeName, + gtag.Path, inputStructTypeName, ) } @@ -116,13 +118,13 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { // Method check. if in.Method == "" { - in.Method = gmeta.Get(inputObject.Interface(), TagNameMethod).String() + in.Method = gmeta.Get(inputObject.Interface(), gtag.Method).String() } if in.Method == "" { return gerror.NewCodef( gcode.CodeMissingParameter, `missing necessary method parameter "%s" for input struct "%s", missing tag in attribute Meta?`, - TagNameMethod, inputStructTypeName, + gtag.Method, inputStructTypeName, ) } @@ -138,8 +140,8 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { return err } // Allowed request mime. - if mime = inputMetaMap[TagNameMime]; mime == "" { - mime = inputMetaMap[TagNameConsumes] + if mime = inputMetaMap[gtag.Mime]; mime == "" { + mime = inputMetaMap[gtag.Consumes] } } @@ -179,7 +181,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { // Supported mime types of request. var ( contentTypes = oai.Config.ReadContentTypes - tagMimeValue = gmeta.Get(inputObject.Interface(), TagNameMime).String() + tagMimeValue = gmeta.Get(inputObject.Interface(), gtag.Mime).String() ) if tagMimeValue != "" { contentTypes = gstr.SplitAndTrim(tagMimeValue, ",") @@ -224,7 +226,7 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { // Supported mime types of response. var ( contentTypes = oai.Config.ReadContentTypes - tagMimeValue = gmeta.Get(outputObject.Interface(), TagNameMime).String() + tagMimeValue = gmeta.Get(outputObject.Interface(), gtag.Mime).String() refInput = getResponseSchemaRefInput{ BusinessStructName: outputStructTypeName, CommonResponseObject: oai.Config.CommonResponse, @@ -256,35 +258,35 @@ func (oai *OpenApiV3) addPath(in addPathInput) error { // Assign to certain operation attribute. switch gstr.ToUpper(in.Method) { - case HttpMethodGet: + case http.MethodGet: // GET operations cannot have a requestBody. operation.RequestBody = nil path.Get = &operation - case HttpMethodPut: + case http.MethodPut: path.Put = &operation - case HttpMethodPost: + case http.MethodPost: path.Post = &operation - case HttpMethodDelete: + case http.MethodDelete: // DELETE operations cannot have a requestBody. operation.RequestBody = nil path.Delete = &operation - case HttpMethodConnect: + case http.MethodConnect: // Nothing to do for Connect. - case HttpMethodHead: + case http.MethodHead: path.Head = &operation - case HttpMethodOptions: + case http.MethodOptions: path.Options = &operation - case HttpMethodPatch: + case http.MethodPatch: path.Patch = &operation - case HttpMethodTrace: + case http.MethodTrace: path.Trace = &operation default: @@ -354,7 +356,7 @@ func (oai *OpenApiV3) doesStructHasNoFields(s interface{}) bool { } func (oai *OpenApiV3) tagMapToPath(tagMap map[string]string, path *Path) error { - var mergedTagMap = oai.fileMapWithShortTags(tagMap) + var mergedTagMap = oai.fillMapWithShortTags(tagMap) if err := gconv.Struct(mergedTagMap, path); err != nil { return gerror.Wrap(err, `mapping struct tags to Path failed`) } diff --git a/net/goai/goai_response.go b/net/goai/goai_response.go index 8961bb395..ce702eda1 100644 --- a/net/goai/goai_response.go +++ b/net/goai/goai_response.go @@ -22,7 +22,7 @@ type Response struct { } func (oai *OpenApiV3) tagMapToResponse(tagMap map[string]string, response *Response) error { - var mergedTagMap = oai.fileMapWithShortTags(tagMap) + var mergedTagMap = oai.fillMapWithShortTags(tagMap) if err := gconv.Struct(mergedTagMap, response); err != nil { return gerror.Wrap(err, `mapping struct tags to Response failed`) } diff --git a/net/goai/goai_shema.go b/net/goai/goai_shema.go index cb3b717d9..8250d064a 100644 --- a/net/goai/goai_shema.go +++ b/net/goai/goai_shema.go @@ -211,7 +211,7 @@ func (oai *OpenApiV3) structToSchema(object interface{}) (*Schema, error) { } func (oai *OpenApiV3) tagMapToSchema(tagMap map[string]string, schema *Schema) error { - var mergedTagMap = oai.fileMapWithShortTags(tagMap) + var mergedTagMap = oai.fillMapWithShortTags(tagMap) if err := gconv.Struct(mergedTagMap, schema); err != nil { return gerror.Wrap(err, `mapping struct tags to Schema failed`) } diff --git a/net/goai/goai_z_unit_test.go b/net/goai/goai_z_unit_test.go index d6af7e983..7274b7ac5 100644 --- a/net/goai/goai_z_unit_test.go +++ b/net/goai/goai_z_unit_test.go @@ -9,6 +9,7 @@ package goai_test import ( "context" "fmt" + "net/http" "testing" "github.com/gogf/gf/v2/frame/g" @@ -96,14 +97,14 @@ func TestOpenApiV3_Add(t *testing.T) { ) err = oai.Add(goai.AddInput{ Path: "/test1/{appId}", - Method: goai.HttpMethodPut, + Method: http.MethodPut, Object: f, }) t.AssertNil(err) err = oai.Add(goai.AddInput{ Path: "/test1/{appId}", - Method: goai.HttpMethodPost, + Method: http.MethodPost, Object: f, }) t.AssertNil(err) @@ -216,7 +217,7 @@ func TestOpenApiV3_Add_AutoDetectIn(t *testing.T) { ) err = oai.Add(goai.AddInput{ Path: path, - Method: goai.HttpMethodGet, + Method: http.MethodGet, Object: f, }) t.AssertNil(err) @@ -654,27 +655,27 @@ func TestOpenApiV3_CommonResponse_SubDataField(t *testing.T) { func TestOpenApiV3_ShortTags(t *testing.T) { type CommonReq struct { - AppId int64 `json:"appId" v:"required" in:"path" des:"应用Id" sum:"应用Id Summary"` - ResourceId string `json:"resourceId" in:"query" des:"资源Id" sum:"资源Id Summary"` + AppId int64 `json:"appId" v:"required" in:"path" dc:"应用Id" sm:"应用Id Summary"` + ResourceId string `json:"resourceId" in:"query" dc:"资源Id" sm:"资源Id Summary"` } type SetSpecInfo struct { - StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" des:"StorageType"` - Shards int32 `des:"shards 分片数" sum:"Shards Summary"` - Params []string `des:"默认参数(json 串-ClickHouseParams)" sum:"Params Summary"` + StorageType string `v:"required|in:CLOUD_PREMIUM,CLOUD_SSD,CLOUD_HSSD" dc:"StorageType"` + Shards int32 `dc:"shards 分片数" sm:"Shards Summary"` + Params []string `dc:"默认参数(json 串-ClickHouseParams)" sm:"Params Summary"` } type CreateResourceReq struct { CommonReq - gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sum:"CreateResourceReq sum"` - Name string `des:"实例名称"` - Product string `des:"业务类型"` - Region string `v:"required" des:"区域"` - SetMap map[string]*SetSpecInfo `v:"required" des:"配置Map"` - SetSlice []SetSpecInfo `v:"required" des:"配置Slice"` + gmeta.Meta `path:"/CreateResourceReq" method:"POST" tags:"default" sm:"CreateResourceReq sum"` + Name string `dc:"实例名称"` + Product string `dc:"业务类型"` + Region string `v:"required" dc:"区域"` + SetMap map[string]*SetSpecInfo `v:"required" dc:"配置Map"` + SetSlice []SetSpecInfo `v:"required" dc:"配置Slice"` } type CreateResourceRes struct { - gmeta.Meta `des:"Demo Response Struct"` - FlowId int64 `des:"创建实例流程id"` + gmeta.Meta `dc:"Demo Response Struct"` + FlowId int64 `dc:"创建实例流程id"` } f := func(ctx context.Context, req *CreateResourceReq) (res *CreateResourceRes, err error) { @@ -688,14 +689,14 @@ func TestOpenApiV3_ShortTags(t *testing.T) { ) err = oai.Add(goai.AddInput{ Path: "/test1/{appId}", - Method: goai.HttpMethodPut, + Method: http.MethodPut, Object: f, }) t.AssertNil(err) err = oai.Add(goai.AddInput{ Path: "/test1/{appId}", - Method: goai.HttpMethodPost, + Method: http.MethodPost, Object: f, }) t.AssertNil(err) @@ -728,7 +729,7 @@ func TestOpenApiV3_HtmlResponse(t *testing.T) { ) err = oai.Add(goai.AddInput{ Path: "/test", - Method: goai.HttpMethodGet, + Method: http.MethodGet, Object: f, }) t.AssertNil(err) @@ -775,7 +776,7 @@ func TestOpenApiV3_HtmlResponseWithCommonResponse(t *testing.T) { err = oai.Add(goai.AddInput{ Path: "/test", - Method: goai.HttpMethodGet, + Method: http.MethodGet, Object: f, }) t.AssertNil(err) diff --git a/os/gcmd/gcmd_command_object.go b/os/gcmd/gcmd_command_object.go index 07c11ed5b..6c352f306 100644 --- a/os/gcmd/gcmd_command_object.go +++ b/os/gcmd/gcmd_command_object.go @@ -23,18 +23,11 @@ import ( "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gmeta" + "github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gutil" "github.com/gogf/gf/v2/util/gvalid" ) -const ( - tagNameDc = `dc` // description. - tagNameAd = `ad` // additional - tagNameEg = `eg` // examples. - tagNameArg = `arg` - tagNameRoot = `root` -) - var ( // defaultValueTags is the struct tag names for default value storing. defaultValueTags = []string{"d", "default"} @@ -68,7 +61,7 @@ func NewFromObject(object interface{}) (rootCmd *Command, err error) { // Sub command creating. var ( nameSet = gset.NewStrSet() - rootCommandName = gmeta.Get(object, tagNameRoot).String() + rootCommandName = gmeta.Get(object, gtag.Root).String() subCommands []*Command ) if rootCommandName == "" { @@ -155,14 +148,22 @@ func newCommandFromObjectMeta(object interface{}, name string) (command *Command } command.Name = name } + if command.Brief == "" { + for _, tag := range []string{gtag.Summary, gtag.SummaryShort, gtag.SummaryShort2} { + command.Brief = metaData[tag] + if command.Brief != "" { + break + } + } + } if command.Description == "" { - command.Description = metaData[tagNameDc] + command.Description = metaData[gtag.DescriptionShort] } if command.Examples == "" { - command.Examples = metaData[tagNameEg] + command.Examples = metaData[gtag.ExampleShort] } if command.Additional == "" { - command.Additional = metaData[tagNameAd] + command.Additional = metaData[gtag.AdditionalShort] } return } @@ -354,7 +355,7 @@ func newArgumentsFromInput(object interface{}) (args []Argument, err error) { arg.Short, reflect.TypeOf(object).String(), field.Name(), ) } - if v, ok := metaData[tagNameArg]; ok { + if v, ok := metaData[gtag.Arg]; ok { arg.IsArg = gconv.Bool(v) } if nameSet.Contains(arg.Name) { diff --git a/util/gtag/gtag.go b/util/gtag/gtag.go index 058159386..a7771f187 100644 --- a/util/gtag/gtag.go +++ b/util/gtag/gtag.go @@ -10,60 +10,35 @@ // which means you cannot call them in runtime but in boot procedure. package gtag -import ( - "regexp" - - "github.com/gogf/gf/v2/errors/gerror" +const ( + Default = "default" // Default value tag of struct field for receiving parameters from HTTP request. + DefaultShort = "d" // Short name of Default. + Param = "param" // Parameter name for converting certain parameter to specified struct field. + ParamShort = "p" // Short name of Param. + Valid = "valid" // Validation rule tag for struct of field. + ValidShort = "v" // Short name of Valid. + NoValidation = "nv" // No validation for specified struct/field. + ORM = "orm" // ORM tag for ORM feature, which performs different features according scenarios. + Arg = "arg" // Arg tag for struct, usually for command argument option. + Brief = "brief" // Brief tag for struct, usually be considered as summary. + Root = "root" // Root tag for struct, usually for nested commands management. + Additional = "additional" // Additional tag for struct, usually for additional description of command. + AdditionalShort = "ad" // Short name of Additional. + Path = `path` // Route path for HTTP request. + Method = `method` // Route method for HTTP request. + Domain = `domain` // Route domain for HTTP request. + Mime = `mime` // MIME type for HTTP request/response. + Consumes = `consumes` // MIME type for HTTP request. + Summary = `summary` // Summary for struct, usually for OpenAPI in request struct. + SummaryShort = `sm` // Short name of Summary. + SummaryShort2 = `sum` // Short name of Summary. + Description = `description` // Description for struct, usually for OpenAPI in request struct. + DescriptionShort = `dc` // Short name of Description. + DescriptionShort2 = `des` // Short name of Description. + Example = `example` // Example for struct, usually for OpenAPI in request struct. + ExampleShort = `eg` // Short name of Example. + Examples = `examples` // Examples for struct, usually for OpenAPI in request struct. + ExamplesShort = `egs` // Short name of Examples. + ExternalDocs = `externalDocs` // External docs for struct, always for OpenAPI in request struct. + ExternalDocsShort = `ed` // Short name of ExternalDocs. ) - -var ( - data = make(map[string]string) - regex = regexp.MustCompile(`\{(.+?)\}`) -) - -// Set sets tag content for specified name. -// Note that it panics if `name` already exists. -func Set(name, value string) { - if _, ok := data[name]; ok { - panic(gerror.Newf(`value for tag name "%s" already exists`, name)) - } - data[name] = value -} - -// SetOver performs as Set, but it overwrites the old value if `name` already exists. -func SetOver(name, value string) { - data[name] = value -} - -// Sets sets multiple tag content by map. -func Sets(m map[string]string) { - for k, v := range m { - Set(k, v) - } -} - -// SetsOver performs as Sets, but it overwrites the old value if `name` already exists. -func SetsOver(m map[string]string) { - for k, v := range m { - SetOver(k, v) - } -} - -// Get retrieves and returns the stored tag content for specified name. -func Get(name string) string { - return data[name] -} - -// Parse parses and returns the content by replacing all tag name variable to -// its content for given `content`. -// Eg: -// gtag.Set("demo", "content") -// Parse(`This is {demo}`) -> `This is content`. -func Parse(content string) string { - return regex.ReplaceAllStringFunc(content, func(s string) string { - if v, ok := data[s[1:len(s)-1]]; ok { - return v - } - return s - }) -} diff --git a/util/gtag/gtag_func.go b/util/gtag/gtag_func.go new file mode 100644 index 000000000..5085c788b --- /dev/null +++ b/util/gtag/gtag_func.go @@ -0,0 +1,65 @@ +// Copyright GoFrame Author(https://goframe.org). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gtag + +import ( + "regexp" + + "github.com/gogf/gf/v2/errors/gerror" +) + +var ( + data = make(map[string]string) + regex = regexp.MustCompile(`\{(.+?)\}`) +) + +// Set sets tag content for specified name. +// Note that it panics if `name` already exists. +func Set(name, value string) { + if _, ok := data[name]; ok { + panic(gerror.Newf(`value for tag name "%s" already exists`, name)) + } + data[name] = value +} + +// SetOver performs as Set, but it overwrites the old value if `name` already exists. +func SetOver(name, value string) { + data[name] = value +} + +// Sets sets multiple tag content by map. +func Sets(m map[string]string) { + for k, v := range m { + Set(k, v) + } +} + +// SetsOver performs as Sets, but it overwrites the old value if `name` already exists. +func SetsOver(m map[string]string) { + for k, v := range m { + SetOver(k, v) + } +} + +// Get retrieves and returns the stored tag content for specified name. +func Get(name string) string { + return data[name] +} + +// Parse parses and returns the content by replacing all tag name variable to +// its content for given `content`. +// Eg: +// gtag.Set("demo", "content") +// Parse(`This is {demo}`) -> `This is content`. +func Parse(content string) string { + return regex.ReplaceAllStringFunc(content, func(s string) string { + if v, ok := data[s[1:len(s)-1]]; ok { + return v + } + return s + }) +} diff --git a/util/gvalid/gvalid.go b/util/gvalid/gvalid.go index f276ac67f..fa0a2b3be 100644 --- a/util/gvalid/gvalid.go +++ b/util/gvalid/gvalid.go @@ -15,6 +15,7 @@ import ( "github.com/gogf/gf/v2/internal/intlog" "github.com/gogf/gf/v2/text/gregex" + "github.com/gogf/gf/v2/util/gtag" ) // CustomMsg is the custom error message type, @@ -42,7 +43,7 @@ const ( internalErrorMapKey = "__InternalError__" // error map key for internal errors. internalDefaultRuleName = "__default__" // default rule name for i18n error message format if no i18n message found for specified error rule. ruleMessagePrefixForI18n = "gf.gvalid.rule." // prefix string for each rule configuration in i18n content. - noValidationTagName = "nv" // no validation tag name for struct attribute. + noValidationTagName = gtag.NoValidation // no validation tag name for struct attribute. ruleNameRegex = "regex" // the name for rule "regex" ruleNameNotRegex = "not-regex" // the name for rule "not-regex" ruleNameForeach = "foreach" // the name for rule "foreach" @@ -60,8 +61,11 @@ var ( internalDefaultRuleName: "The {field} value `{value}` is invalid", } - structTagPriority = []string{"gvalid", "valid", "v"} // structTagPriority specifies the validation tag priority array. - aliasNameTagPriority = []string{"param", "params", "p"} // aliasNameTagPriority specifies the alias tag priority array. + // structTagPriority specifies the validation tag priority array. + structTagPriority = []string{gtag.Valid, gtag.ValidShort} + + // aliasNameTagPriority specifies the alias tag priority array. + aliasNameTagPriority = []string{gtag.Param, gtag.ParamShort} // all internal error keys. internalErrKeyMap = map[string]string{ diff --git a/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go b/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go index b31be9412..b9037d00a 100755 --- a/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go +++ b/util/gvalid/gvalid_z_unit_feature_checkstruct_test.go @@ -116,8 +116,8 @@ func Test_CheckStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { type LoginRequest struct { - Username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + Username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } var login LoginRequest err := g.Validator().Data(login).Run(context.TODO()) @@ -129,8 +129,8 @@ func Test_CheckStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { type LoginRequest struct { - Username string `json:"username" gvalid:"@required#用户名不能为空"` - Password string `json:"password" gvalid:"@required#登录密码不能为空"` + Username string `json:"username" valid:"@required#用户名不能为空"` + Password string `json:"password" valid:"@required#登录密码不能为空"` } var login LoginRequest err := g.Validator().Data(login).Run(context.TODO()) @@ -139,8 +139,8 @@ func Test_CheckStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { type LoginRequest struct { - username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } var login LoginRequest err := g.Validator().Data(login).Run(context.TODO()) @@ -151,10 +151,10 @@ func Test_CheckStruct(t *testing.T) { // gvalid tag gtest.C(t, func(t *gtest.T) { type User struct { - Id int `gvalid:"uid@required|min:10#|ID不能为空"` - Age int `gvalid:"age@required#年龄不能为空"` - Username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + Id int `valid:"uid@required|min:10#|ID不能为空"` + Age int `valid:"age@required#年龄不能为空"` + Username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } user := &User{ Id: 1, @@ -169,10 +169,10 @@ func Test_CheckStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { type User struct { - Id int `gvalid:"uid@required|min:10#|ID不能为空"` - Age int `gvalid:"age@required#年龄不能为空"` - Username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + Id int `valid:"uid@required|min:10#|ID不能为空"` + Age int `valid:"age@required#年龄不能为空"` + Username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } user := &User{ Id: 1, @@ -192,10 +192,10 @@ func Test_CheckStruct(t *testing.T) { gtest.C(t, func(t *gtest.T) { type User struct { - Id int `gvalid:"uid@required|min:10#ID不能为空"` - Age int `gvalid:"age@required#年龄不能为空"` - Username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + Id int `valid:"uid@required|min:10#ID不能为空"` + Age int `valid:"age@required#年龄不能为空"` + Username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } user := &User{ Id: 1, @@ -212,8 +212,8 @@ func Test_CheckStruct(t *testing.T) { type User struct { Id int `valid:"uid@required|min:10#|ID不能为空"` Age int `valid:"age@required#年龄不能为空"` - Username string `json:"username" gvalid:"username@required#用户名不能为空"` - Password string `json:"password" gvalid:"password@required#登录密码不能为空"` + Username string `json:"username" valid:"username@required#用户名不能为空"` + Password string `json:"password" valid:"password@required#登录密码不能为空"` } user := &User{ Id: 1,