diff --git a/content/en/docs/hertz/tutorials/basic-feature/binding-and-validate.md b/content/en/docs/hertz/tutorials/basic-feature/binding-and-validate.md index 2b6126e9430..e01161d6644 100644 --- a/content/en/docs/hertz/tutorials/basic-feature/binding-and-validate.md +++ b/content/en/docs/hertz/tutorials/basic-feature/binding-and-validate.md @@ -3,7 +3,7 @@ title: "Binding and validate" date: 2025-12-08 weight: 8 keywords: - ["Binding and validate", "go-tagexpr", "tag", "Parameter binding precedence"] + ["Binding and validate", "tag", "Parameter binding precedence"] description: "The parameter binding and validation related functions and usage supported by Hertz." --- @@ -16,7 +16,7 @@ func main() { r.GET("/hello", func(ctx context.Context, c *app.RequestContext) { // Parameter binding needs to be used with a specific go tag type Test struct { - A string `query:"a" vd:"$!='Hertz'"` + A string `query:"a"` } // BindAndValidate @@ -30,11 +30,6 @@ func main() { err = c.Bind(&req) ... - - // Validate, need to use "vd" tag - err = c.Validate(&req) - - ... }) ... } @@ -55,7 +50,7 @@ func main() { | ctx.BindJSON | Bind JSON Body, call `json.Unmarshal()` for deserialization, need Body to be in `application/json` format | | ctx.BindProtobuf | Bind Protobuf Body, call `proto.Unmarshal()` for deserialization, requires Body to be in `application/x-protobuf` format | | ctx.BindByContentType | The binding method is automatically selected based on the Content-Type, where GET requests call `BindQuery`, and requests with Body are automatically selected based on the Content-Type. | -| ctx.Validate | Parameter checksums, which require a checksum tag to be used (vd tag checksums are used by default) | +| ctx.Validate | Perform parameter validation, requires a validation tag (e.g. `validate` tag from go-playground/validator) | ## Supported tags and Parameter binding precedence @@ -74,32 +69,8 @@ If [api-annotations](/docs/hertz/tutorials/toolkit/annotation/#supported-api-ann | header | This tag is used to bind header parameters in request | | json | This tag is used to bind json parameters in the request body which content-type is `application/json` | | raw_body | This tag is used to bind the original body (bytes type) of the request, and parameters can be bound even if the bound field name is not specified. (Note: raw_body has the lowest binding priority. When multiple tags are specified, once other tags successfully bind parameters, the body content will not be bound) | -| vd | `vd` short for validator, [The grammar of validation parameter](https://github.com/bytedance/go-tagexpr/tree/master/validator) | | default | Set default value | -### Parameter Validation - -Specific validation syntax can be referred to [The grammar of validation parameter](https://github.com/bytedance/go-tagexpr/tree/master/validator). - -When generating code without IDL, directly tag the corresponding structure field, for example: - -```go -type InfoRequest struct { - Name string `vd:"$!='your string'"` -} -``` - -When generating code through IDL, corresponding annotations need to be added, please refer to [field-annotation](/docs/hertz/tutorials/toolkit/annotation/#field-annotation). - -Here are common usage examples: - -- length validation for string and list `len($)>0` -- regex pattern match for string `regexp('^\\w*$')"` -- value validation for numertic field `$>0` -- validation for pointer field `num==nil || num>0` -- validation for enum types `type=="hello" || type == "world"` -- custom error message `msg:'C must be false when S.A>0'"` - ### Parameter binding precedence ```text @@ -124,13 +95,8 @@ type TagRequiredReq struct { ## Common config -> hertz has refactored `parameter binding` and `checksum` in version v0.7.0, which changes the behaviour of the configurations, as described below
respectively. -> If you still want to use the previous binder, it is now implemented under [hertz-contrib/binding](https://github.com/hertz-contrib/binding) and can be introduced via a custom binder. - ### Customise binder -> hertz version >= v0.10.3 support - You need to implement the Binder interface and inject it into the hertz engine in a configurable way. ```go @@ -200,13 +166,6 @@ func (m *mockBinder) Validate(request *protocol.Request, i interface{}) error { ``` -Currently expanded binders: - -> ⚠️ Note: The `hertz-contrib/binding` middleware is now deprecated. -> Users are recommended to use built-in functionality in Hertz or their own custom binder. - -- bytedance/go-tagexpr: https://github.com/hertz-contrib/binding/tree/main/go_tagexpr (binding library used before refactoring) - ### Custom validator > Supported by hertz version >= v0.10.3. @@ -227,59 +186,9 @@ func main() { } ``` -#### Custom validator (Deprecated) - -> Supported by Hertz versions 0.7.0 to 0.10.2. - -You need to implement the Validator interface and inject it into the hertz engine in a configurable way. - -```go -type StructValidator interface { - ValidateStruct(interface{}) error // Validation function. - Engine() interface{} // Returns the underlying Validator. - ValidateTag() string // Validation tag, declares the tag used by the validator. -} -``` - -Example - -```go - -func main() { - // Inject the custom binder via configuration - h := server.New(server.WithCustomValidator(&mockValidator{})) - ... - h.Spin() -} - -type mockValidator struct{} - -func (m *mockValidator) ValidateStruct(interface{}) error { - return fmt.Errorf("test mock validator") -} - -func (m *mockValidator) Engine() interface{} { - return nil -} - -func (m *mockValidator) ValidateTag() string { - return "vt" -} - -``` - -Currently expanded validators: - -> ⚠️ Note: The `hertz-contrib/binding` middleware is now deprecated. -> Users are recommended to use the built-in functionality in Hertz. If custom validation is required, users can use the validator from [go-playground/validator](https://github.com/go-playground/validator). - -- go-playground/validator: https://github.com/hertz-contrib/binding/tree/main/go_playground - ### Customize the error of binding and validation -When an error occurs in the binding parameter and the parameter validation fails, user can customize the Error([demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_error))For example: -The user can customise the content of the Error in case of binding parameter errors and parameter validation failures, using the following method:
-**hertz version >= v0.10.3** +When an error occurs in the binding parameter and the parameter validation fails, user can customize the Error([demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_error)). > Custom bind errors are not supported at this time. @@ -354,104 +263,9 @@ func main() { } ``` -**hertz versions 0.7.0 to 0.10.2**
- -```go -package main - -import ( - "github.com/cloudwego/hertz/pkg/app/server/binding" - "github.com/cloudwego/hertz/pkg/app/server" -) - -type ValidateError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *ValidateError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -func main() { - validateConfig := &binding.ValidateConfig{} - validateConfig.SetValidatorErrorFactory(func(failField, msg string) error { - err := ValidateError{ - ErrType: "validateErr", - FailField: "[validateFailField]: " + failField, - Msg: "[validateErrMsg]: " + msg, - } - - return &err - }) - h := server.New(server.WithValidateConfig(validateConfig)) - ... - h.Spin() -} -``` - -**hertz version < v0.7.0**
-[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_error) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -type BindError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *BindError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -type ValidateError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *ValidateError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -func init() { - CustomBindErrFunc := func(failField, msg string) error { - err := BindError{ - ErrType: "bindErr", - FailField: "[bindFailField]: " + failField, - Msg: "[bindErrMsg]: " + msg, - } - - return &err - } - - CustomValidateErrFunc := func(failField, msg string) error { - err := ValidateError{ - ErrType: "validateErr", - FailField: "[validateFailField]: " + failField, - Msg: "[validateErrMsg]: " + msg, - } - - return &err - } - - binding.SetErrorFactory(CustomBindErrFunc, CustomValidateErrFunc) -} -``` - ### Customize type resolution -In the parameter binding, for some special types, when the default behavior can not meet the demand, you can use the custom type resolution to solve the problem, the use of the following:
-**hertz version >= v0.7.0**
+In the parameter binding, for some special types, when the default behavior can not meet the demand, you can use the custom type resolution to solve the problem, the use of the following: ```go package main @@ -472,8 +286,6 @@ type TestBind struct { func main() { bindConfig := binding.NewBindConfig() - // After v0.7.0 refactoring, on the basis of the original increase in the request content and routing parameters, - // which can be more flexible for the user to customise the type of parsing // Note: Only after a tag is successfully matched will the custom logic go through. bindConfig.MustRegTypeUnmarshal(reflect.TypeOf(Nested{}), func(req *protocol.Request, params param.Params, text string) (reflect.Value, error) { if text == "" { @@ -493,40 +305,9 @@ func main() { } ``` -**hertz version < v0.7.0**
- -[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_type_resolve) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -type Nested struct { - B string - C string -} - -type TestBind struct { - A Nested `query:"a,required"` -} - -func init() { - binding.MustRegTypeUnmarshal(reflect.TypeOf(Nested{}), func(v string, emptyAsZero bool) (reflect.Value, error) { - if v == "" && emptyAsZero { - return reflect.ValueOf(Nested{}), nil - } - val := Nested{ - B: v[:5], - C: v[5:], - } - return reflect.ValueOf(val), nil - }) -} -``` - ### Custom validation function -Complex validation logic can be implemented in the `validate` annotation by registering a custom validation function:
-**hertz version >= v0.10.3**
+Complex validation logic can be implemented by registering a custom validation function with go-playground/validator: ```go package main @@ -537,7 +318,6 @@ import ( "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" - "github.com/cloudwego/hertz/pkg/app/server/binding" "github.com/cloudwego/hertz/pkg/protocol" "github.com/go-playground/validator/v10" ) @@ -573,61 +353,9 @@ func main() { } ``` -**hertz versions 0.7.0 to 0.10.2**
- -```go -package main - -import ( - "github.com/cloudwego/hertz/pkg/app/server/binding" - "github.com/cloudwego/hertz/pkg/app/server" -) - -func main() { - type Req struct { - A int `query:"a" vd:"test($)"` - } - validateConfig := &binding.ValidateConfig{} - validateConfig.MustRegValidateFunc("test", func(args ...interface{}) error { - if len(args) != 1 { - return fmt.Errorf("the args must be one") - } - s, _ := args[0].(string) - if s == "123" { - return fmt.Errorf("the args can not be 123") - } - return nil - }) - h := server.New(server.WithValidateConfig(validateConfig)) - ... - h.Spin() -} -``` - -**hertz version < v0.7.0**
-[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_validate_func) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - binding.MustRegValidateFunc("test", func(args ...interface{}) error { - if len(args) != 1 { - return fmt.Errorf("the args must be one") - } - s, _ := args[0].(string) - if s == "123" { - return fmt.Errorf("the args can not be 123") - } - return nil - }) -} -``` - ### Configure looseZero In some scenarios, the front-end sometimes passes information that only has a key but not a value, which can lead to errors when binding numeric types; then you need to configure looseZero mode, which can be used as follows: -**hertz version >= v0.7.0**
```go package main @@ -639,8 +367,6 @@ import ( func main() { bindConfig := binding.NewBindConfig() - // Works for the current Hertz Engine, no conflicts between multiple engine instances bindConfig. - // By default, looseZeroMode is false, and the global configuration is not affected bindConfig.LooseZeroMode = true h := server.New(server.WithBindConfig(bindConfig)) ... @@ -648,21 +374,9 @@ func main() { } ``` -**hertz version < v0.7.0**
- -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - // False by default, globally effective, if other components also use the same configuration, configuration conflicts may occur - binding.SetLooseZeroMode(true) -} -``` - ### Configure other json unmarshal libraries When binding parameters, if the request body is json, a json unmarshal will be performed. If users need to use other json libraries (hertz uses the open source json library [sonic](https://github.com/bytedance/sonic) by default), they can configure it themselves. For example: -**hertz version >= v0.7.0**
```go import ( @@ -680,23 +394,6 @@ func main() { } ``` -**hertz version < v0.7.0**
- -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - // Use the standard library as a JSON deserialisation tool - binding.UseStdJSONUnmarshaler() - - // Use GJSON as the JSON deserialisation tool. - binding.UseGJSONUnmarshaler() - - // Use third-party JSON libraries as JSON deserialisers. - binding.UseThirdPartyJSONUnmarshaler() -} -``` - ### Set default values The parameter supports the `default` tag to configure the default value. For example: diff --git a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md index 57da62668eb..88c4714d250 100644 --- a/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md +++ b/content/en/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md @@ -44,7 +44,6 @@ This specification is the IDL definition standard for mapping between Thrift and | `api.cookie` | `api. cookie `corresponds cookie parameter for HTTP request | Only basic types are supported | ✅ | | ` api.body` | `api.body `corresponds body parameter for HTTP request
Both serialization type like `json` and `form` in body are supported | `Json` is supported by default . The `api.serializer` annotation for `method` can sepify serialization `json or form` | ✅, but only `json` format | | `api.raw_body` | `api.raw_body` corresponds raw body for HTTP request, we can get raw binary body | | ✅ | -| `api.vd` | Parameter valid, we can refer [HTTPs://github.com/bytedance/go-tagexpr/tree/master/validator](HTTPs://github.com/bytedance/go-tagexpr/tree/master/validator) for details | | ❌ | | `api.js_conv` | `api.js_conv` indicates the field should be string while the definition is in64, since int64 is not supported by typescript | The annotation value should be `true`, if else will be treated as invalid | ✅ | | `api.raw_uri` | `api.raw_uri` is used for protocol exchange from HTTP to RPC, the RPC service can get the raw uri by the field | Only `string` type is supported | ❌ | diff --git a/content/zh/docs/hertz/tutorials/basic-feature/binding-and-validate.md b/content/zh/docs/hertz/tutorials/basic-feature/binding-and-validate.md index e92506e040c..0dc15a16932 100644 --- a/content/zh/docs/hertz/tutorials/basic-feature/binding-and-validate.md +++ b/content/zh/docs/hertz/tutorials/basic-feature/binding-and-validate.md @@ -2,7 +2,7 @@ title: "绑定与校验" date: 2025-12-08 weight: 8 -keywords: ["绑定与校验", "go-tagexpr", "tag", "参数绑定优先级"] +keywords: ["绑定与校验", "tag", "参数绑定优先级"] description: "Hertz 支持的参数绑定与校验相关功能及用法。" --- @@ -15,7 +15,7 @@ func main() { r.GET("/hello", func(ctx context.Context, c *app.RequestContext) { // 参数绑定需要配合特定的 go tag 使用 type Test struct { - A string `query:"a" vd:"$!='Hertz'"` + A string `query:"a"` } // BindAndValidate @@ -29,11 +29,6 @@ func main() { err = c.Bind(&req) ... - - // Validate,需要使用 "vd" tag - err = c.Validate(&req) - - ... }) ... } @@ -54,7 +49,7 @@ func main() { | ctx.BindJSON | 绑定 JSON Body,调用 `json.Unmarshal()` 进行反序列化,需要 Body 为 `application/json` 格式 | | ctx.BindProtobuf | 绑定 Protobuf Body,调用 `proto.Unmarshal()` 进行反序列化,需要 Body 为 `application/x-protobuf` 格式 | | ctx.BindByContentType | 根据 Content-Type 来自动选择绑定的方法,其中 GET 请求会调用 `BindQuery`, 带有 Body 的请求会根据 Content-Type 自动选择 | -| ctx.Validate | 进行参数校验,需要校验 tag 配合使用 (默认使用 vd tag 校验) | +| ctx.Validate | 进行参数校验,需要校验 tag 配合使用(如 go-playground/validator 的 `validate` tag) | ## 支持的 tag 及参数绑定优先级 @@ -73,32 +68,8 @@ func main() { | header | 绑定请求的 header 参数 | | json | 绑定请求的 body 内容 content-type -> `application/json`,绑定 json 参数 | | raw_body | 绑定请求的原始 body(bytes),绑定的字段名不指定,也能绑定参数。(注:raw_body 绑定优先级最低,当指定多个 tag 时,一旦其他 tag 成功绑定参数,则不会绑定 body 内容。) | -| vd | 参数校验,[校验语法](https://github.com/bytedance/go-tagexpr/tree/master/validator) | | default | 设置默认值 | -### 参数校验 - -具体校验语法可参考 [校验语法](https://github.com/bytedance/go-tagexpr/tree/master/validator)。 - -不通过 IDL 生成代码时直接在对应结构体字段打 tag,示例: - -```go -type InfoRequest struct { - Name string `vd:"$!='your string'"` -} -``` - -通过 IDL 生成代码时需添加相应的注解,可参考 [Field 注解](/zh/docs/hertz/tutorials/toolkit/annotation/#field-注解)。 - -下面给出常见用法: - -- string 和 list 的长度验证 `len($)>0` -- 字符串正则匹配 `regexp('^\\w*$')"` -- 验证数字字段的的值 `$>0` -- 验证指针字段 `num==nil || num>0` -- 验证枚举类型 `type=="hello" || type == "world"` -- 自定义错误信息 `msg:'C must be false when S.A>0'"` - ### 参数绑定优先级 ```text @@ -123,13 +94,8 @@ type TagRequiredReq struct { ## 常用配置 -> hertz 在 v0.7.0 版本对 `参数绑定`和`校验` 进行了重构,重构后配置的行为发生变更,下面将分别介绍
-> 如果还想使用之前的绑定器,目前已把其实现放到了 [hertz-contrib/binding](https://github.com/hertz-contrib/binding) 下,可通过自定义 binder 引入 - ### 自定义 binder -> hertz version >= v0.10.3 支持 - 需要实现 Binder 接口,并通过配置方式注入到 hertz engine ```go @@ -199,13 +165,6 @@ func (m *mockBinder) Validate(request *protocol.Request, i interface{}) error { ``` -目前已拓展的绑定器: - -> ⚠️ 注意:`hertz-contrib/binding` 中间件已被废弃。 -> 建议用户使用 Hertz 内置功能或自定义绑定器。 - -- bytedance/go-tagexpr: https://github.com/hertz-contrib/binding/tree/main/go_tagexpr (重构前使用的绑定库) - ### 自定义 validator > hertz version >= v0.10.3 支持 @@ -226,58 +185,9 @@ func main() { } ``` -#### 自定义 validator (已废弃) - -> hertz versions 0.7.0 至 0.10.2 支持 - -需要实现 Validator 接口,并通过配置方式注入到 hertz engine - -```go -type StructValidator interface { - ValidateStruct(interface{}) error // 校验函数 - Engine() interface{} // 返回底层的 Validator - ValidateTag() string // 校验的 tag, 声明校验器使用的 tag -} -``` - -注入示例 - -```go - -func main() { - // 通过配置的方式注入自定义 binder - h := server.New(server.WithCustomValidator(&mockValidator{})) - ... - h.Spin() -} - -type mockValidator struct{} - -func (m *mockValidator) ValidateStruct(interface{}) error { - return fmt.Errorf("test mock validator") -} - -func (m *mockValidator) Engine() interface{} { - return nil -} - -func (m *mockValidator) ValidateTag() string { - return "vt" -} - -``` - -目前已拓展的校验器: - -> ⚠️ 注意:`hertz-contrib/binding` 中间件已被废弃。 -> 建议用户使用 Hertz 内置的功能。如果需要自定义验证,用户可以使用 [go-playground/validator](https://github.com/go-playground/validator) 中的 validator。 - -- go-playground/validator: https://github.com/hertz-contrib/binding/tree/main/go_playground - ### 自定义 bind 和 validate 的 Error -在绑定参数发生错误和参数校验失败的时候,用户可以自定义 Error 的内容,使用方法如下:
-**hertz version >= v0.10.3** +在绑定参数发生错误和参数校验失败的时候,用户可以自定义 Error 的内容,使用方法如下: > 暂不支持自定义 bind error @@ -352,103 +262,9 @@ func main() { } ``` -**hertz versions 0.7.0 至 0.10.2**
- -```go -package main -import ( - "github.com/cloudwego/hertz/pkg/app/server/binding" - "github.com/cloudwego/hertz/pkg/app/server" -) - -type ValidateError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *ValidateError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -func main() { - validateConfig := &binding.ValidateConfig{} - validateConfig.SetValidatorErrorFactory(func(failField, msg string) error { - err := ValidateError{ - ErrType: "validateErr", - FailField: "[validateFailField]: " + failField, - Msg: "[validateErrMsg]: " + msg, - } - - return &err - }) - h := server.New(server.WithValidateConfig(validateConfig)) - ... - h.Spin() -} -``` - -**hertz version < v0.7.0**
-[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_error) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -type BindError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *BindError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -type ValidateError struct { - ErrType, FailField, Msg string -} - -// Error implements error interface. -func (e *ValidateError) Error() string { - if e.Msg != "" { - return e.ErrType + ": expr_path=" + e.FailField + ", cause=" + e.Msg - } - return e.ErrType + ": expr_path=" + e.FailField + ", cause=invalid" -} - -func init() { - CustomBindErrFunc := func(failField, msg string) error { - err := BindError{ - ErrType: "bindErr", - FailField: "[bindFailField]: " + failField, - Msg: "[bindErrMsg]: " + msg, - } - - return &err - } - - CustomValidateErrFunc := func(failField, msg string) error { - err := ValidateError{ - ErrType: "validateErr", - FailField: "[validateFailField]: " + failField, - Msg: "[validateErrMsg]: " + msg, - } - - return &err - } - - binding.SetErrorFactory(CustomBindErrFunc, CustomValidateErrFunc) -} -``` - ### 自定义类型解析 -在参数绑定的时候,针对某些特殊类型,当默认行为无法满足需求时,可使用自定义类型解析来解决,使用方法如下:
-**hertz version >= v0.7.0**
+在参数绑定的时候,针对某些特殊类型,当默认行为无法满足需求时,可使用自定义类型解析来解决,使用方法如下: ```go package main @@ -469,8 +285,7 @@ type TestBind struct { func main() { bindConfig := binding.NewBindConfig() - // v0.7.0 重构后,在原基础上增加了请求 Request 内容以及路由参数,可方便用户更加灵活的自定义类型解析 - // 注意:只有 tag 成功匹配后,才会走到自定义的逻辑 + // 注意:只有 tag 成功匹配后,才会走到自定义的逻辑 bindConfig.MustRegTypeUnmarshal(reflect.TypeOf(Nested{}), func(req *protocol.Request, params param.Params, text string) (reflect.Value, error) { if text == "" { return reflect.ValueOf(Nested{}), nil @@ -489,40 +304,9 @@ func main() { } ``` -**hertz version < v0.7.0**
- -[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_type_resolve) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -type Nested struct { - B string - C string -} - -type TestBind struct { - A Nested `query:"a,required"` -} - -func init() { - binding.MustRegTypeUnmarshal(reflect.TypeOf(Nested{}), func(v string, emptyAsZero bool) (reflect.Value, error) { - if v == "" && emptyAsZero { - return reflect.ValueOf(Nested{}), nil - } - val := Nested{ - B: v[:5], - C: v[5:], - } - return reflect.ValueOf(val), nil - }) -} -``` - ### 自定义验证函数 -可以通过注册自定义验证函数,在 `validate` 注解中实现复杂的验证逻辑:
-**hertz version >= v0.10.3**
+可以通过使用 go-playground/validator 注册自定义验证函数,实现复杂的验证逻辑: ```go package main @@ -533,7 +317,6 @@ import ( "github.com/cloudwego/hertz/pkg/app" "github.com/cloudwego/hertz/pkg/app/server" - "github.com/cloudwego/hertz/pkg/app/server/binding" "github.com/cloudwego/hertz/pkg/protocol" "github.com/go-playground/validator/v10" ) @@ -569,61 +352,9 @@ func main() { } ``` -**hertz versions 0.7.0 至 0.10.2**
- -```go -package main - -import ( - "github.com/cloudwego/hertz/pkg/app/server/binding" - "github.com/cloudwego/hertz/pkg/app/server" -) - -func main() { - type Req struct { - A int `query:"a" vd:"test($)"` - } - validateConfig := &binding.ValidateConfig{} - validateConfig.MustRegValidateFunc("test", func(args ...interface{}) error { - if len(args) != 1 { - return fmt.Errorf("the args must be one") - } - s, _ := args[0].(string) - if s == "123" { - return fmt.Errorf("the args can not be 123") - } - return nil - }) - h := server.New(server.WithValidateConfig(validateConfig)) - ... - h.Spin() -} -``` - -**hertz version < v0.7.0**
-[demo](https://github.com/cloudwego/hertz-examples/tree/main/binding/custom_validate_func) - -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - binding.MustRegValidateFunc("test", func(args ...interface{}) error { - if len(args) != 1 { - return fmt.Errorf("the args must be one") - } - s, _ := args[0].(string) - if s == "123" { - return fmt.Errorf("the args can not be 123") - } - return nil - }) -} -``` - ### 配置 looseZero 在一些场景下,前端有时候传来的信息只有 key 没有 value,这会导致绑定数值类型的时候报错;这时需要配置 looseZero 模式,使用方法如下: -**hertz version >= v0.7.0**
```go package main @@ -635,7 +366,6 @@ import ( func main() { bindConfig := binding.NewBindConfig() - // 默认 false,当前 Hertz Engine 下生效,多份 engine 实例之间不会冲突 bindConfig.LooseZeroMode = true h := server.New(server.WithBindConfig(bindConfig)) ... @@ -643,21 +373,9 @@ func main() { } ``` -**hertz version < v0.7.0**
- -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - // 默认 false,全局生效,如果其他组件也使用相关配置,可能会发生配置冲突 - binding.SetLooseZeroMode(true) -} -``` - ### 配置其他 json unmarshal 库 -在绑定参数的时候,如果请求体为 json,会进行一次 json 的 unmarshal,如果用户需要使用特定的 json 库可以自行配置(hertz 默认使用开源 json 库 [sonic](https://github.com/bytedance/sonic) )。使用方法如下:
-**hertz version >= v0.7.0**
+在绑定参数的时候,如果请求体为 json,会进行一次 json 的 unmarshal,如果用户需要使用特定的 json 库可以自行配置(hertz 默认使用开源 json 库 [sonic](https://github.com/bytedance/sonic) )。使用方法如下: ```go import ( @@ -675,27 +393,8 @@ func main() { } ``` -**hertz version < v0.7.0**
- -```go -import "github.com/cloudwego/hertz/pkg/app/server/binding" - -func init() { - // 使用标准库作为 JSON 反序列化工具 - binding.UseStdJSONUnmarshaler() - - // 使用 GJSON 作为 JSON 反序列化工具 - binding.UseGJSONUnmarshaler() - - // 使用第三方 JSON 库作为 JSON 反序列化工具 - binding.UseThirdPartyJSONUnmarshaler() -} -``` - ### 设置默认值 -> 重构前后使用方式都一样 - 参数支持 `default` tag 进行默认值的配置,使用方法如下: ```go @@ -707,8 +406,7 @@ type UserInfoResponse struct { ### 绑定文件 -> 重构前后使用方式一样,IDL 场景不支持文件绑定 -> 文件类型需为:`multipart.FileHeader` +> 文件类型需为:`multipart.FileHeader`,IDL 场景不支持文件绑定 参数绑定支持绑定文件,使用方法如下: diff --git a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md index 3e34bb1d598..273b9680bfe 100644 --- a/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md +++ b/content/zh/docs/kitex/Tutorials/advanced-feature/generic-call/thrift_idl_annotation_standards.md @@ -44,7 +44,6 @@ description: > | `api.cookie` | `api.cookie` 对应 HTTP 的 cookie 参数 | 支持基本类型 | 支持 | | `api.body` | `api.body` 对应 HTTP 的 body 参数
支持 body 为 `json` 和 `form` 两种格式 | 在未指定接口序列化方式下默认`json`格式,也可以在`method`注解中使用`api.serializer`来指定`json/form` | 支持,但目前仅支持 `JSON` 格式 | | `api.raw_body` | `api.raw_body` HTTP 原始 body,少数接口 body 加密了,可以拿到原始的 body(二进制数组) | | 支持 | -| `api.vd` | 参数校验,使用了[HTTPs://github.com/bytedance/go-tagexpr/tree/master/validator](HTTPs://github.com/bytedance/go-tagexpr/tree/master/validator)库,检验表达式语法参见包内readme文件 | | 暂未支持 | | `api.js_conv` | `api.js_conv` 标识该字段传入参数需要进行 string to int64 转换,来解决前端 js 不支持 int64 的场景 | value通常写true,其它情况与不写该注解等价 | 支持 | | `api.raw_uri` | `api.raw_uri` 用于 HTTP to RPC 协议转换,RPC 服务获取 HTTP接口对应的原始 uri | 只支持 `string` 类型 | 暂未支持 |