Skip to content

Commit 5dcf01f

Browse files
authored
Feat v1 (#12)
* rename rules
1 parent 376fa04 commit 5dcf01f

29 files changed

+684
-817
lines changed

.travis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
dist: bionic
2+
13
language: go
24

35
go:
@@ -6,10 +8,8 @@ go:
68
install:
79
- go get golang.org/x/tools/cmd/cover
810
- go get github.com/mattn/goveralls
9-
- go get golang.org/x/lint/golint
1011

1112
script:
1213
- test -z "`gofmt -l -d .`"
13-
- test -z "`golint ./...`"
1414
- go test -v -covermode=count -coverprofile=coverage.out
1515
- $HOME/gopath/bin/goveralls -coverprofile=coverage.out -service=travis-ci

README.md

Lines changed: 30 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -24,182 +24,40 @@ go get -u github.com/liangyaopei/checker
2424

2525
## Usage
2626

27-
Examples are in test files which have suffix `test`.
27+
When use `Add` to add rule,`fieldExpr` has three situations:
28+
- `fieldExpr` is empty,validate the value directly.
29+
- `fieldExpr` is single field,fetch value in struct, then validate.
30+
- `fieldExpr` is string separated by `.`, fetch value in struct according hierarchy of struct, then validate.
2831

29-
The main principle is, every validation rule is a `Rule` interface, `Rule` validates parameter, returns `isValid` and error log.
30-
31-
`Checker` is a validatior, it adds `Rule` and error prompt on related fileld in struct.
32-
33-
34-
35-
For example, [non-struct parameter validation](nonstruct_test.go), `fieldExpr` is empty string.
36-
37-
```go
38-
email := "abc@examplecom"
39-
40-
nonStructChecker := checker.NewChecker()
41-
42-
emailRule := checker.NewEmailRule("")
43-
nonStructChecker.Add(emailRule, "invalid email")
44-
45-
isValid, prompt, errMsg := nonStructChecker.Check(email)
46-
```
47-
48-
49-
50-
[struct parameter validation](timestamp_test.go)
51-
52-
```go
53-
type timestamp struct {
54-
StartDateStr string
55-
}
56-
57-
layout := "2006-01-02"
58-
startDate, _ := time.Parse(layout, "2020-12-12")
59-
60-
tsChecker := checker.NewChecker()
61-
tsStrRule := checker.NewEqRuleTimestampStr("StartDateStr", layout, startDate)
62-
tsChecker.Add(tsStrRule, "invalid StartDateStr")
63-
64-
ts := timestamp{
65-
StartDateStr: "2020-12-12",
66-
}
67-
isValid, prompt, errMsg := tsChecker.Check(ts)
68-
```
69-
70-
[customized validation rule](customized_rule_test.go), only implements `Rule` interface.
71-
72-
73-
74-
## Rule realted to corresponding tag in validator.v10
75-
76-
### Cross filed comparasion
77-
78-
| tag | Rule |
79-
| ------------- | ------------------------------------------------------------ |
80-
| eqfield | `NewCrossFieldCompareRule("Int1", "Int2", checker.CrossFieldEq)` |
81-
| fieldcontains | `NewEnumRuleInt("Value", []int{8, 9, 10})` |
82-
| fieldexcludes | `Not(checker.NewEnumRuleInt("Value", []int{8, 9, 10}))` |
83-
| gtfield | `NewCrossFieldCompareRule("Int1", "Int2", CrossFieldGt)` |
84-
| gtefield | `NewCrossFieldCompareRule("Int1", "Int2", checker.CrossFieldGe)` |
85-
| nefield | `NewCrossFieldCompareRule("Int1", "Int2", checker.CrossFieldNe)` |
86-
87-
88-
89-
### Strings
90-
91-
| tag | Rule | |
92-
| ---------------- | ------------------------------------- | ---- |
93-
| alpha | `NewAlphaRule("Field")` | |
94-
| alphanum | `NewAlphaNumericRule("Field")` | |
95-
| email | `NewEmailRule("Email")` | |
96-
| isbn10 | `NewISBN10Rule("Field")` | |
97-
| isbn10 | `NewISBN13Rule("Field")` | |
98-
| isbn | `NewISBNRuke("Field")` | |
99-
| ip | `NewIPRule(FieldExpr)` | |
100-
| ipv4 | `NewIPv4Rule("IPv4")` | |
101-
| ipv6 | `NewIPv6Rule("IPv6")` | |
102-
| uri | `NewURIRule("URL")` | |
103-
| url | `NewURLRule("URL")` | |
104-
| url_encoded | `NewURLEncodedRule("Field")` | |
105-
| html | `NewHTMLRule("Field")` | |
106-
| html_encoded | `NewHTMLEncodedRule("Field")` | |
107-
| hostname | `NewHostNameRule("Field")` | |
108-
| hostname_rfc1123 | `NewHostNameRFC1123Rule("Field")` | |
109-
| json | `NewIsJSONRule("Field")` | |
110-
| dir | `NewIsDirRule("Field")` | |
111-
| datetime | `NewIsDatetimeRule("Field","layout")` | |
112-
113-
etc, regrex expression for string rule, can use `NewRegexRule(fieldExpr string, regexExpr string)`
114-
115-
116-
117-
### Comparasion
118-
119-
| Tag | Rule |
120-
| -------------- | --------------------------------------------------------- |
121-
| eq | `NewEqRuleInt(filedExpr string, equivalent int)` ... |
122-
| gt, gte,lt,lte | `NewRangeRuleInt(filedExpr string, ge int, le int)` ... |
123-
| ne | `NewNotEqRuleInt(filedExpr string, inequivalent int)` ... |
124-
125-
126-
127-
### Slice/Array/Map
128-
129-
| Rule | Usage |
130-
| ------------------------------------------------------------ | ------------------------------------------------------------ |
131-
| `NewSliceRule(fieldExpr string, innerRule Rule) ` | apply `innerRule` to every elements in slice/array |
132-
| `NewMapRule(fieldExpr string, keyRule Rule, valueRule Rule)` | apply `keyRule` to keys in map, and `ValueRule` to valuse in map. `keyRule` or `ValueRule` can be nil. |
133-
134-
135-
136-
### Others
137-
138-
| Tag | Rule |
139-
| ------------------------------- | ------------------------------------------------------------ |
140-
| len | `NewLengthRule(fieldExpr string, ge int, le int)` |
141-
| required_if, required_without,etc | implemented by compositions of `NewAndRule(rules []Rule) Rule`, `NewOrRule(rules []Rule)`, `NewNotRule(innerRule Rule)` |
142-
143-
144-
145-
### easy for checker, hard for validatior
146-
147-
The main drawback of `validator` is, validation rule is attached to fields in struct via tag, which is intrusive, and hard to read the validation logic.
148-
149-
1. validation sturct of third party
15032

15133
```go
152-
package thrid_party
153-
154-
type Param struct{
155-
Age `validate:"min=18,max=80"`
34+
type Item struct {
35+
Info typeInfo
15636
}
157-
```
158-
159-
In user's package, try to change min to 20, `validator` can not change the validation rule, as we cannot change the struct layout outside our packages.
16037

161-
```go
162-
package main
163-
164-
func validate(p thrid_party.Param)(isValid bool){
165-
....
38+
// typeInfo.Type = "range", length of typeInfo.Type is 2,elements meets format of "2006-01-02"
39+
// typeInfo.Type = "last", length of typeInfo.Typeis 1,elements meets of format positive integer,
40+
// Granularity must be one of day/week/month
41+
type typeInfo struct {
42+
Type string
43+
Range []string
44+
Unit string
45+
Granularity string
16646
}
16747

168-
```
169-
170-
If use `checker`, the rule is simpler:
171-
172-
```go
173-
rule := checker.NewRangeRuleInt("Age", 20, 80)
174-
checker.Add(rule, "invlaid age")
175-
```
176-
177-
178-
Because validation rule of `checker` is decoupled from struct, which makes changes validation rule easy.
179-
180-
2. validate the length of linkedlist
181-
182-
The example is [here](_checker_test/linkedlist_test.go).
183-
184-
```go
185-
type list struct {
186-
Name *string
187-
Next *list `validate:"nonzero"`
188-
}
189-
```
190-
191-
To validate the length of linkedlist, requiring the first node's `Next` cannot be nil. `validator` cannot do this, for the same tag is attached to the same field.
192-
193-
If use `checker`
194-
195-
```go
196-
name := "list"
197-
node1 := list{Name: &name, Next: nil}
198-
lists := list{Name: &name, Next: &node1}
199-
200-
listChecker := checker.NewChecker()
201-
nameRule := checker.NewLengthRule("Next.Name", 1, 20)
202-
listChecker.Add(nameRule, "invalid info name")
203-
```
204-
205-
Length can be defined by `Next.Name`
48+
// here is the rule
49+
rule := Field("Info",
50+
Or(
51+
And(
52+
EqStr("Type", "range"),
53+
Length("Range", 2, 2),
54+
Array("Range", isDatetime("", "2006-01-02")),
55+
),
56+
And(
57+
EqStr("Type", "last"),
58+
InStr("Granularity", "day", "week", "month"),
59+
Number("Unit"),
60+
),
61+
),
62+
)
63+
```

0 commit comments

Comments
 (0)