github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/binding/README.md (about) 1 # binding [![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/bytedance/go-tagexpr/binding) 2 3 A powerful HTTP request parameters binder that supports struct tag expression. 4 5 ## Example 6 7 ```go 8 func Example() { 9 type InfoRequest struct { 10 Name string `path:"name"` 11 Year []int `query:"year"` 12 Email *string `json:"email" vd:"email($)"` 13 Friendly bool `json:"friendly"` 14 Status string `json:"status" default:"single"` 15 Pie float32 `json:"pie,required"` 16 Hobby []string `json:",required"` 17 BodyNotFound *int `json:"BodyNotFound"` 18 Authorization string `header:"Authorization,required" vd:"$=='Basic 123456'"` 19 SessionID string `cookie:"sessionid,required"` 20 AutoBody string 21 AutoNotFound *string 22 TimeRFC3339 time.Time `query:"t"` 23 } 24 25 args := new(InfoRequest) 26 binder := binding.New(nil) 27 err := binder.BindAndValidate(args, requestExample(), new(testPathParams)) 28 29 fmt.Println("bind and validate result:") 30 31 fmt.Printf("error: %v\n", err) 32 33 b, _ := json.MarshalIndent(args, "", " ") 34 fmt.Printf("args JSON string:\n%s\n", b) 35 36 // Output: 37 // request: 38 // POST /info/henrylee2cn?year=2018&year=2019&t=2019-09-04T18%3A04%3A08%2B08%3A00 HTTP/1.1 39 // Host: localhost 40 // User-Agent: Go-http-client/1.1 41 // Transfer-Encoding: chunked 42 // Authorization: Basic 123456 43 // Content-Type: application/json;charset=utf-8 44 // Cookie: sessionid=987654 45 // 46 // 83 47 // {"AutoBody":"autobody_test","Hobby":["Coding","Mountain climbing"],"email":"henrylee2cn@gmail.com","friendly":true,"pie":3.1415926} 48 // 0 49 // 50 // bind and validate result: 51 // error: <nil> 52 // args JSON string: 53 // { 54 // "Name": "henrylee2cn", 55 // "Year": [ 56 // 2018, 57 // 2019 58 // ], 59 // "email": "henrylee2cn@gmail.com", 60 // "friendly": true, 61 // "status": "single", 62 // "pie": 3.1415925, 63 // "Hobby": [ 64 // "Coding", 65 // "Mountain climbing" 66 // ], 67 // "BodyNotFound": null, 68 // "Authorization": "Basic 123456", 69 // "SessionID": "987654", 70 // "AutoBody": "autobody_test", 71 // "AutoNotFound": null, 72 // "TimeRFC3339": "2019-09-04T18:04:08+08:00" 73 // } 74 } 75 ... 76 ``` 77 78 ## Syntax 79 80 The parameter position in HTTP request: 81 82 |expression|renameable|description| 83 |----------|----------|-----------| 84 |`path:"$name"` or `path:"$name,required"`|Yes|URL path parameter| 85 |`query:"$name"` or `query:"$name,required"`|Yes|URL query parameter| 86 |`raw_body:""` or `raw_body:"required"`|Yes|The raw bytes of body| 87 |`form:"$name"` or `form:"$name,required"`|Yes|The field in body, support:<br>`application/x-www-form-urlencoded`,<br>`multipart/form-data`| 88 |`protobuf:"...(raw syntax)"`|No|The field in body, support:<br>`application/x-protobuf`| 89 |`json:"$name"` or `json:"$name,required"`|No|The field in body, support:<br>`application/json`| 90 |`header:"$name"` or `header:"$name,required"`|Yes|Header parameter| 91 |`cookie:"$name"` or `cookie:"$name,required"`|Yes|Cookie parameter| 92 |`default:"$value"`|Yes|Default parameter| 93 |`vd:"...(tagexpr validator syntax)"`|Yes|The tagexpr expression of validator| 94 95 **NOTE:** 96 97 - `"$name"` is variable placeholder 98 - If `"$name"` is empty, use the name of field 99 - If `"$name"` is `-`, omit the field 100 - Expression `required` or `req` indicates that the parameter is required 101 - `default:"$value"` defines the default value for fallback when no binding is successful 102 - If no position is tagged, try bind parameters from the body when the request has body, 103 <br>otherwise try bind from the URL query 104 - When there is unexportable and no tags, omit the field 105 - When there are multiple tags, or exportable and no tags, the order in which to try to bind is: 106 1. path 107 2. form 108 3. query 109 4. cookie 110 5. header 111 6. protobuf 112 7. json 113 8. default 114 115 ## Type Unmarshalor 116 117 TimeRFC3339-binding function is registered by default. 118 119 Register your own binding function for the specified type, e.g.: 120 121 ```go 122 MustRegTypeUnmarshal(reflect.TypeOf(time.Time{}), func(v string, emptyAsZero bool) (reflect.Value, error) { 123 if v == "" && emptyAsZero { 124 return reflect.ValueOf(time.Time{}), nil 125 } 126 t, err := time.Parse(time.RFC3339, v) 127 if err != nil { 128 return reflect.Value{}, err 129 } 130 return reflect.ValueOf(t), nil 131 }) 132 ```