{"id":19674734,"url":"https://github.com/cloudwego/thrift-gen-validator","last_synced_at":"2026-03-10T17:33:42.264Z","repository":{"id":41065615,"uuid":"380962470","full_name":"cloudwego/thrift-gen-validator","owner":"cloudwego","description":"thrift-gen-validator is a thriftgo plugin to generate struct validators.","archived":false,"fork":false,"pushed_at":"2025-02-08T09:50:26.000Z","size":127,"stargazers_count":20,"open_issues_count":0,"forks_count":9,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-29T02:39:25.290Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cloudwego.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-28T08:36:16.000Z","updated_at":"2025-04-04T03:55:54.000Z","dependencies_parsed_at":"2023-11-30T08:26:33.565Z","dependency_job_id":"3bdbec64-bc65-4ec7-95d7-8bc16a9fe841","html_url":"https://github.com/cloudwego/thrift-gen-validator","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/cloudwego/thrift-gen-validator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudwego%2Fthrift-gen-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudwego%2Fthrift-gen-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudwego%2Fthrift-gen-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudwego%2Fthrift-gen-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cloudwego","download_url":"https://codeload.github.com/cloudwego/thrift-gen-validator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cloudwego%2Fthrift-gen-validator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30344467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:55:29.454Z","status":"ssl_error","status_checked_at":"2026-03-10T15:54:58.440Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T17:19:35.973Z","updated_at":"2026-03-10T17:33:42.241Z","avatar_url":"https://github.com/cloudwego.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# thrift-gen-validator\n\nthrift-gen-validator is a thriftgo plugin to generate struct validators.\nUsers can define validation rule for struct-like(struct/union/exception) in Thrift file, then the generator will generate `IsValid() error` method for those structs.\n\nfor example:\n\n```Thrift\nenum MapKey {\n    A, B, C, D, E, F\n}\n\nstruct Example {\n    1: string Message (vt.min_size = \"30\") // length of Message should be greater than or equal to 30\n    2: i32 ID (vt.ge = \"10000\") // ID must be greater than or euqal to 10000\n    3: list\u003cdouble\u003e Values (vt.elem.gt = \"0.25\") // element of Values must be greater than 0.25\n    4: map\u003cMapKey, string\u003e KeyValues (vt.key.defined_only = \"true\") // value of KeyValues'key must be defined in MapKey\n}\n```\n\ngenerated method:\n\n```go\nfunc (p *Example) IsValid() error {\n\tif len(p.Message) \u003c int(30) {\n\t\treturn fmt.Errorf(\"field Message min_len rule failed, current value: %d\", len(p.Message))\n\t}\n\tif p.ID \u003c int32(10000) {\n\t\treturn fmt.Errorf(\"field ID ge rule failed, current value: %v\", p.ID)\n\t}\n\tfor i := 0; i \u003c len(p.Values); i++ {\n\t\t_elem := p.Values[i]\n\t\tif _elem \u003c= float64(0.25) {\n\t\t\treturn fmt.Errorf(\"field _elem gt rule failed, current value: %v\", _elem)\n\t\t}\n\t}\n\tfor k := range p.KeyValues {\n\t\tif k.String() == \"\u003cUNSET\u003e\" {\n\t\t\treturn fmt.Errorf(\"field k defined_only rule failed\")\n\t\t}\n\t}\n\treturn nil\n}\n```\n\n## Install\n\n`go install github.com/cloudwego/thrift-gen-validator@latest`\n\n## Usage\n\n### Thriftgo\n\n`thriftgo -g go -p validator my.thrift`\n\n### Kitex\n\n`kitex --thrift-plugin validator -service a.b.c my.thrift`\n\n## Feature Matrix\n\nprefix `vt`, short for \"validation\"\n\n### Numeric(i8/i16/i32/i64/double)\n\n| Rule      |                                          |\n| --------- | ---------------------------------------- |\n| vt.const  | must be specified value                  |\n| vt.lt     | less than the specified value            |\n| vt.le     | less than or equal to specified value    |\n| vt.gt     | greater than the specified value         |\n| vt.ge     | greater than or equal to specified value |\n| vt.in     | must be in specified values              |\n| vt.not_in | must not be in specified values          |\n\n### Bool\n\n| Rule     |                         |\n| -------- | ----------------------- |\n| vt.const | must be specified value |\n\n### String/Binary\n\n| Rule             |                                  |\n|------------------|----------------------------------|\n| vt.const         | must be specified value          |\n| vt.pattern       | regexp pattern                   |\n| vt.prefix        | prefix must be specified value   |\n| vt.suffix        | suffix must be specified value   |\n| vt.contains      | must contain specified value     |\n| vt.not_contains  | must not contain specified value |\n| vt.min_size      | min size                         |\n| vt.max_size      | max size                         |\n| vt.max_rune_size | max rune size                    |\n| vt.min_rune_size | min rune size                    |\n\n### Enum\n\n| Rule            |                         |\n| --------------- | ----------------------- |\n| vt.const        | must be specified value |\n| vt.defined_only | must be defined value   |\n\n### Set/List\n\n| Rule        |                       |\n| ----------- | --------------------- |\n| vt.min_size | min size              |\n| vt.max_size | max size              |\n| vt.elem     | rule for list element |\n\n### Map\n\n| Rule         |                                   |\n| ------------ | --------------------------------- |\n| vt.min_size  | min size                          |\n| vt.max_size  | max size                          |\n| vt.key       | rule for map key                  |\n| vt.value     | rule for map value                |\n| vt.no_sparse | map value must be non-nil pointer |\n\n### Struct Field\n\n| Rule    |                                  |\n| ------- | -------------------------------- |\n| vt.skip | skip struct recursive validation |\n\n### Struct\n\n| Rule      |                           |\n| --------- | ------------------------- |\n| vt.assert | expression should be true |\n\n### Special Value\n\n1. Field Reference. We can use another field as a validation value.\n2. Validation Function. We can use those functions to provide extensive validation ability.\n\n#### Field Reference Example\n\n```Thrift\nstruct Example {\n    1: string StringFoo (vt.max_size = \"$MaxStringSize\")\n    2: i32 MaxStringSize\n}\n```\n\n#### Validation Function\n\n```Thrift\nstruct Example {\n    1: string MaxString\n    2: list\u003cstring\u003e StringList (vt.elem.max_size = \"@len($MaxString)\")\n}\n```\n\n| function name | arguments                                             | results                                                | remarks                                 |\n| ------------- | ----------------------------------------------------- | ------------------------------------------------------ | --------------------------------------- |\n| len           | 1: container field                                    | 1: length of container (integer)                       | just like `len` of go                   |\n| sprintf       | 1: format string \u003cbr /\u003e 2+: arguments matching format | 1: formatted string (string)                           | just like `fmt.Sprintf` of go           |\n| now_unix_nano | none                                                  | 1: nano seconds (int64)                                | just like `time.Now().UnixNano()` of go |\n| equal         | 1, 2: comparable values                               | 1: whether two arguments is equal (bool)               | just like `==` of go                    |\n| mod           | 1, 2: integer                                         | 1: remainder of $1 / $2 (integer)                      | just like `%` of go                     |\n| add           | 1, 2: both are numeric or string                      | 1: sum of two arguments (integer or float64 or string) | just like `+` of go                     |\n\n#### Customized Validation Function\n\nNow you can use parameter `func` to customize your validation function. Like below:  \n`thriftgo -g go -p validator:func=my_func=path_to_template.txt my.thrift`  \n`my_func` is the function name, `path_to_template.txt` is the path to template file which should be a go template.\nAvailable template variables:\n| variable name | meaning                               | type                                                             |\n| ------------- | ------------------------------------- | ---------------------------------------------------------------- |\n| Source        | variable name that rule will refer to | string                                                           |\n| StructLike    | ast of current struct/union/exception | *\"github.com/cloudwego/thriftgo/generator/golang\".StructLike     |\n| Function      | data of current function              | *\"github.com/cloudwego/thrift-gen-validator/parser\".ToolFunction |\n\n## Example\n\n### Kitex Middleware Example\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/cloudwego/kitex-examples/kitex_gen/api\"\n\t\"github.com/cloudwego/kitex-examples/kitex_gen/api/echo\"\n\t\"github.com/cloudwego/kitex/client\"\n\t\"github.com/cloudwego/kitex/pkg/endpoint\"\n\t\"github.com/cloudwego/kitex/server\"\n)\n\nfunc ValidatorMW(next endpoint.Endpoint) endpoint.Endpoint {\n\treturn func(ctx context.Context, args, result interface{}) (err error) {\n\t\tif gfa, ok := args.(interface{ GetFirstArgument() interface{} }); ok {\n\t\t\treq := gfa.GetFirstArgument()\n\t\t\tif rv, ok := req.(interface{ IsValid() error }); ok {\n\t\t\t\tif err := rv.IsValid(); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"request data is not valid:%w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\terr = next(ctx, args, result)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif gr, ok := result.(interface{ GetResult() interface{} }); ok {\n\t\t\tresp := gr.GetResult()\n\t\t\tif rv, ok := resp.(interface{ IsValid() error }); ok {\n\t\t\t\tif err := rv.IsValid(); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"response data is not valid:%w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn nil\n\t}\n}\n\n// for client\nfunc main() {\n\tcli := echo.MustNewClient(\"service_name\", client.WithMiddleware(ValidatorMW))\n\tresp, err := client.Echo(context.Background(), \u0026api.Request{Message: \"my request\"})\n\tif err != nil {\n\t\tlog.Println(err.Error())\n\t} else {\n\t\tlog.Println(resp)\n\t}\n}\n\n// for server\nfunc main() {\n\tsvr := echo.NewServer(new(EchoImpl), server.WithMiddleware(ValidatorMW))\n\terr := svr.Run()\n\tif err != nil {\n\t\tlog.Println(err.Error())\n\t}\n}\n```\n\n### Customize Validation Function Example\nIf we have a `my.thrift` like below:\n\n```Thrift\nstruct Example {\n    1: string Message (vt.max_size = \"@my_length()\")\n}\n```\n\nAnd assumes that we want to limit the max length of `Message` to 10, we can write a template file `my_length.txt` like below:\n\n```template\n{{- .Source}} := 10 /*my length*/\n```\n\nThen we can use command below to generate a validator file:  \n`thriftgo -g go -p validator:func=my_length=my_length.txt my.thrift`\n\nWe will get a `IsValid() error` like below:\n\n```go\nfunc (p *ValidatorExample) IsValid() error {\n\t_src := 10 /*my length*/\n\tif len(p.Message) \u003e int(_src) {\n\t\treturn fmt.Errorf(\"field Message max_len rule failed, current value: %d\", len(p.Message))\n\t}\n\treturn nil\n}\n```\n\n`{{.Source}}` indicates `_src` which will be used in `if len(p.Message) \u003e int(_src) {`, so all the thing the function template need to do is assign a value to `_src` aka `{{.Source}}`. In the above example, `{{- .Source}} := + 10 /*my length*/` will do.\n\nNow let's see a more complex example. Assumes that we have a `my.thrift` like below:\n\n```Thrift\nstruct Example {\n    1: string Message (vt.max_size = \"@fix_length($MaxLength)\")\n    2: i64 MaxLength\n}\n```\n\nAnd assumes that we want to limit the max length of `Message` to the sum of MaxLength and 10, we can write a template file `fix_length.txt` like below:\n\n```template\n{{- $arg0 := index .Function.Arguments 0}}\n{{- $reference := $arg0.TypedValue.GetFieldReferenceName \"p.\" .StructLike}}\n{{- .Source}} := {{$reference}} + 10 /*length fix*/\n```\n\nThen we can use command below to generate a validator file:  \n`thriftgo -g go -p validator:func=fix_length=fix_length.txt my.thrift`\n\nWe will get a `IsValid() error` like below:\n\n```go\nfunc (p *ValidatorExample) IsValid() error {\n\t_src := p.MaxLength + 10 /*length fix*/\n\tif len(p.Message) \u003e int(_src) {\n\t\treturn fmt.Errorf(\"field Message max_len rule failed, current value: %d\", len(p.Message))\n\t}\n\treturn nil\n}\n```\n\n`{{$arg0 := index .Function.Arguments 0}}` is used to get the first argument of the function. `{{$reference := $arg0.TypedValue.GetFieldReferenceName \"p.\" .StructLike}}` is used to get the reference name of the first argument, for there `p.MaxLength`.\n\nIn some scenarios, we might want to import some extra packages, for example, if we want to get some enviroment variables, we need to import `os` package which is not in the default import list. In this case, we can add following statement to function template file:\n\n```template\n{{define \"Import\"}}\n\"os\"\n{{end}}\n{{define \"ImportGuard\"}}\n_ = os.Getenv\n{{end}}\n```\n\nThen we can get a validator go file header like below:\n\n```go\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"regexp\"\n\t\"strings\"\n\t\"time\"\n)\n\n// unused protection\nvar (\n\t_ = fmt.Formatter(nil)\n\t_ = (*bytes.Buffer)(nil)\n\t_ = (*strings.Builder)(nil)\n\t_ = reflect.Type(nil)\n\t_ = (*regexp.Regexp)(nil)\n\t_ = time.Nanosecond\n\t_ = os.Getenv\n)\n```\n\nYou can go to [examples/custom-function](/examples/custom-function/) to see the complete example. And you can view the generated code in [examples/custom-function/gen-go/my](/examples/custom-function/gen-go/my/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudwego%2Fthrift-gen-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcloudwego%2Fthrift-gen-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcloudwego%2Fthrift-gen-validator/lists"}