-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
228 additions
and
513 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ go get github.com/Rhyanz46/go-map-validator/map_validator | |
``` | ||
|
||
### discussion or updates | ||
|
||
- [On Telegram](https://t.me/addlist/Wi84VFNkvz85MWFl) | ||
|
||
## Features | ||
|
@@ -19,9 +20,9 @@ go get github.com/Rhyanz46/go-map-validator/map_validator | |
- validate data from `http.Request` json/multipart | ||
- support file upload | ||
- Unique Value | ||
- ex case : `old_password` and `new_password` cant be using same value | ||
- ex case : `old_password` and `new_password` cant be using same value | ||
- RequiredWithout check | ||
- ex case : the field `flavor` is required if `custom_flavor` is null | ||
- ex case : the field `flavor` is required if `custom_flavor` is null | ||
- enum value check | ||
- min/max length data check | ||
- email field check | ||
|
@@ -30,7 +31,8 @@ go get github.com/Rhyanz46/go-map-validator/map_validator | |
- IPv4 Network check | ||
- regex on string validation | ||
- nested validation 🔥 | ||
- you can create your own extension 🔥🔥🔥🔥 (example : [https://github.com/Rhyanz46/go-map-validator/example_extensions/](https://github.com/Rhyanz46/go-map-validator/tree/main/example_extensions)) | ||
- you can create your own extension 🔥🔥🔥🔥 ( | ||
example : [https://github.com/Rhyanz46/go-map-validator/example_extensions/](https://github.com/Rhyanz46/go-map-validator/tree/main/example_extensions)) | ||
- custom message : | ||
- on invalid regex message : ✅ ready | ||
- on type not match message : ✅ ready | ||
|
@@ -55,7 +57,6 @@ go get github.com/Rhyanz46/go-map-validator/map_validator | |
| 5 | `${expected_min_length}` | | ||
| 6 | `${expected_max_length}` | | ||
|
||
|
||
## Road Map | ||
|
||
- get from urls params http | ||
|
@@ -65,191 +66,225 @@ go get github.com/Rhyanz46/go-map-validator/map_validator | |
- image resolution validation | ||
- multi validation on one field (ex : IPv4: true, UUID: true) | ||
|
||
|
||
## example : | ||
|
||
### Example 1 | ||
|
||
```go | ||
payload := map[string]interface{}{"jenis_kelamin": "laki-laki", "hoby": "Main PS", "umur": 1, "menikah": true} | ||
err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.String, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.String, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
}, | ||
).Load(payload).RunValidate() | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
|
||
err = map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.Int, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.Int, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
}, | ||
).Load(payload).RunValidate() | ||
if err == nil { | ||
t.Error("Expected have an error, but you got no error") | ||
t.Error("Expected have an error, but you got no error") | ||
} | ||
``` | ||
|
||
### Example 2 ( Nested Object Validation ) | ||
|
||
```go | ||
filterRole := map[string]map_validator.Rules{ | ||
"search": {Type: reflect.String, Null: true}, | ||
"organization_id": {UUID: true, Null: true}, | ||
"search": {Type: reflect.String, Null: true}, | ||
"organization_id": {UUID: true, Null: true}, | ||
} | ||
jsonDataRoles := map_validator.NewValidateBuilder().StrictKeys().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"filter": {Object: &filterRole, Null: true}, | ||
"rows_per_page": {Type: reflect.Int64, Null: true}, | ||
"page_index": {Type: reflect.Int64, Null: true}, | ||
"sort": { | ||
Null: true, | ||
IfNull: "FULL_NAME:DESC", | ||
Type: reflect.String, Enum: &map_validator.EnumField[any]{ | ||
Items: []string{"FULL_NAME:DESC", "FULL_NAME:ASC", "EMAIL:ASC", "EMAIL:DESC"}, | ||
}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"filter": {Object: &filterRole, Null: true}, | ||
"rows_per_page": {Type: reflect.Int64, Null: true}, | ||
"page_index": {Type: reflect.Int64, Null: true}, | ||
"sort": { | ||
Null: true, | ||
IfNull: "FULL_NAME:DESC", | ||
Type: reflect.String, Enum: &map_validator.EnumField[any]{ | ||
Items: []string{"FULL_NAME:DESC", "FULL_NAME:ASC", "EMAIL:ASC", "EMAIL:DESC"}, | ||
}, | ||
}, | ||
} | ||
}) | ||
``` | ||
 | ||
|
||
 | ||
|
||
### Example 3 ( Echo Framework ) | ||
|
||
```go | ||
func handleLogin(c echo.Context) error { | ||
jsonHttp, err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"email": {Email: true, Max: map_validator.SetTotal(100)}, | ||
"password": {Type: reflect.String, Min: map_validator.SetTotal(6), Max: map_validator.SetTotal(30)}, | ||
}, | ||
}).LoadJsonHttp(c.Request()) | ||
if err != nil { | ||
return c.JSON(http.StatusBadRequest, err) | ||
} | ||
err = jsonHttp.RunValidate() | ||
if err != nil { | ||
return c.JSON(http.StatusBadRequest, err) | ||
} | ||
return c.NoContent(http.StatusOK) | ||
jsonHttp, err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"email": {Email: true, Max: map_validator.SetTotal(100)}, | ||
"password": {Type: reflect.String, Min: map_validator.SetTotal(6), Max: map_validator.SetTotal(30)}, | ||
}, | ||
}).LoadJsonHttp(c.Request()) | ||
if err != nil { | ||
return c.JSON(http.StatusBadRequest, err) | ||
} | ||
err = jsonHttp.RunValidate() | ||
if err != nil { | ||
return c.JSON(http.StatusBadRequest, err) | ||
} | ||
return c.NoContent(http.StatusOK) | ||
} | ||
|
||
func main() { | ||
e := echo.New() | ||
e.POST("/login", handleLogin) | ||
e.Start(":3000") | ||
e := echo.New() | ||
e.POST("/login", handleLogin) | ||
e.Start(":3000") | ||
} | ||
|
||
``` | ||
|
||
### Example 4 ( Bind To Struct ) | ||
|
||
```go | ||
type Data struct { | ||
JK string `map_validator:"jenis_kelamin"` | ||
Hoby string `map_validator:"hoby"` | ||
Menikah bool `map_validator:"menikah"` | ||
JK string `map_validator:"jenis_kelamin"` | ||
Hoby string `map_validator:"hoby"` | ||
Menikah bool `map_validator:"menikah"` | ||
} | ||
|
||
payload := map[string]interface{}{"jenis_kelamin": "laki-laki", "hoby": "Main PS", "umur": 1, "menikah": true} | ||
err := map_validator.NewValidateBuilder().SetRules(map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.String, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"jenis_kelamin": {Enum: &map_validator.EnumField[any]{Items: []string{"laki-laki", "perempuan"}}}, | ||
"hoby": {Type: reflect.String, Null: false}, | ||
"menikah": {Type: reflect.Bool, Null: false}, | ||
}, | ||
}).Load(payload).RunValidate() | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
|
||
testBind := &Data{} | ||
if testBind.JK != "" { | ||
t.Errorf("Expected : '' But you got : %s", testBind.JK) | ||
t.Errorf("Expected : '' But you got : %s", testBind.JK) | ||
} | ||
err = extraCheck.Bind(testBind) | ||
if err != nil { | ||
t.Errorf("Error : %s ", err) | ||
t.Errorf("Error : %s ", err) | ||
} | ||
|
||
if testBind.JK != payload["jenis_kelamin"] { | ||
t.Errorf("Expected : %s But you got : %s", payload["jenis_kelamin"], testBind.JK) | ||
t.Errorf("Expected : %s But you got : %s", payload["jenis_kelamin"], testBind.JK) | ||
} | ||
|
||
``` | ||
|
||
|
||
### Example 5 ( Custom message ) | ||
|
||
```go | ||
payload := map[string]interface{}{"total": 12, "unit": "KG"} | ||
validRole := map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"total": { | ||
Type: reflect.Int, | ||
CustomMsg: map_validator.CustomMsg{ | ||
OnTypeNotMatch: map_validator.SetMessage("Total must be a number, but your input is ${actual_type}"), | ||
}, | ||
}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"total": { | ||
Type: reflect.Int, | ||
CustomMsg: map_validator.CustomMsg{ | ||
OnTypeNotMatch: map_validator.SetMessage("Total must be a number, but your input is ${actual_type}"), | ||
}, | ||
}, | ||
}, | ||
} | ||
|
||
check, err := map_validator.NewValidateBuilder().SetRules(validRole).Load(payload) | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
_, err = check.RunValidate() | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
|
||
``` | ||
|
||
|
||
### Example 6 ( Regex validator ) | ||
|
||
```go | ||
payload := map[string]interface{}{"hp": "+62567888", "email": "[email protected]"} | ||
validRole := map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"hp": {RegexString: `^\+(?:\d{2}[- ]?\d{6}|\d{11})$`}, | ||
"email": {RegexString: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"hp": {RegexString: `^\+(?:\d{2}[- ]?\d{6}|\d{11})$`}, | ||
"email": {RegexString: `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`}, | ||
}, | ||
} | ||
check, err := map_validator.NewValidateBuilder().SetRules(validRole).Load(payload) | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
_, err = check.RunValidate() | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
} | ||
|
||
``` | ||
|
||
|
||
### Example 7 ( Unique value ) | ||
|
||
```go | ||
role := map_validator.RulesWrapper{ | ||
Rules: map[string]map_validator.Rules{ | ||
"password": {Type: reflect.String, Unique: []string{"password"}, Null: true}, | ||
"new_password": {Type: reflect.String, Unique: []string{"password"}, Null: true}, | ||
}, | ||
Rules: map[string]map_validator.Rules{ | ||
"password": {Type: reflect.String, Unique: []string{"password"}, Null: true}, | ||
"new_password": {Type: reflect.String, Unique: []string{"password"}, Null: true}, | ||
}, | ||
} | ||
payload := map[string]interface{}{ | ||
"password": "sabalong", | ||
"new_password": "sabalong", | ||
"password": "sabalong", | ||
"new_password": "sabalong", | ||
} | ||
check, err := map_validator.NewValidateBuilder().SetRules(role).Load(payload) | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
return | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
return | ||
} | ||
expected := "value of 'password' and 'new_password' fields must be different" | ||
_, err = check.RunValidate() | ||
if err.Error() != expected { | ||
t.Errorf("Expected :%s. But you got : %s", expected, err) | ||
t.Errorf("Expected :%s. But you got : %s", expected, err) | ||
} | ||
``` | ||
|
||
### Example 8 ( Manipulator ) | ||
|
||
```go | ||
data := map[string]interface{}{ | ||
"description": "test arian keren bgt kan \n\n mantap bukan", | ||
"note": "coba aja mungkin bisa \t mantap", | ||
} | ||
|
||
trimAfterValidation := func (i interface{}) (result interface{}, e error) { | ||
x := i.(string) | ||
result = trimAndClean(x) | ||
return | ||
} | ||
|
||
roles := map_validator.BuildRoles(). | ||
SetRule("description", map_validator.Rules{Type: reflect.String}). | ||
SetRule("note", map_validator.Rules{Type: reflect.String}). | ||
SetManipulator("description", &trimAfterValidation). | ||
Done() | ||
|
||
xx, err := map_validator.NewValidateBuilder().SetRules(roles).Load(data) | ||
extraCheck, err := xx.RunValidate() | ||
if err != nil { | ||
t.Errorf("Expected not have error, but got error : %s", err) | ||
return | ||
} | ||
if extraCheck.GetData()["description"] != "test arian keren bgt kan mantap bukan" { | ||
t.Errorf("Expected description to be test arian keren bgt kan mantap bukan, but got %s", data["description"]) | ||
} | ||
``` |
Oops, something went wrong.