-
Notifications
You must be signed in to change notification settings - Fork 2
constraint.GreaterThanOther
marrow16 edited this page Jan 21, 2023
·
6 revisions
Check that a numeric value is greater than another named property value
Note: this constraint is strict - if either the current or other property is not numeric then this constraint fails
gto
Field | Type | Description |
---|---|---|
PropertyName |
string | the property name of the other value to compare against |
Message |
string | the violation message to be used if the constraint fails. If empty, the default message is used |
Stop |
bool | when set to true, Stop prevents further validation checks on the property if this constraint fails |
Note: the PropertyName
field can also be JSON dot notation path - where leading dots allow traversal up
the object tree and names, separated by dots, allow traversal down the object tree.
A single dot at start is equivalent to no starting dot (i.e. a property name at the same level)
Programmatic example...
package main
import (
"fmt"
"github.com/marrow16/valix"
)
func main() {
validator := &valix.Validator{
Properties: valix.Properties{
"start": {
Type: valix.JsonNumber,
},
"end": {
Type: valix.JsonNumber,
Constraints: valix.Constraints{
&valix.GreaterThanOther{
PropertyName: "start",
},
},
},
},
}
obj := `{"start": 2, "end": 1.5}`
ok, violations, _ := validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
obj = `{"start": 2, "end": 2.0}`
ok, violations, _ = validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
obj = `{"start": 1.0, "end": 2}`
ok, violations, _ = validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
}
Struct v8n tag example...
package main
import (
"fmt"
"github.com/marrow16/valix"
)
type MyStruct struct {
Start float64 `json:"start"`
End float64 `json:"end" v8n:">o{'start'}"`
}
var validator = valix.MustCompileValidatorFor(MyStruct{}, nil)
func main() {
obj := `{"start": 2, "end": 1.5}`
ok, violations, _ := validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
obj = `{"start": 2, "end": 2.0}`
ok, violations, _ = validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
obj = `{"start": 1.0, "end": 2}`
ok, violations, _ = validator.ValidateString(obj)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
}
With relative array value...
package main
import (
"fmt"
"net/http"
"strings"
"github.com/marrow16/valix"
)
type NumbersRequest struct {
Numbers []float64 `json:"numbers" v8n:"type:array,&aof{Type:'number', Constraints:[&acond{When:'!first', Constraint:>o{PropertyName:'[-1]',Msg:'Must be greater than previous'}}]}"`
}
var numbersReqValidator = valix.MustCompileValidatorFor(NumbersRequest{}, nil)
func main() {
numbersRequest := &NumbersRequest{}
req := buildSimulatedHttpReq(`{"numbers":[1,0,2]}`)
ok, violations, _ := numbersReqValidator.RequestValidateInto(req, numbersRequest)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
req = buildSimulatedHttpReq(`{"numbers":[1,2,3]}`)
ok, violations, _ = numbersReqValidator.RequestValidateInto(req, numbersRequest)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
}
func buildSimulatedHttpReq(body string) *http.Request {
req, _ := http.NewRequest("POST", "example.com/test", strings.NewReader(body))
return req
}
With path traversal...
package main
import (
"fmt"
"github.com/marrow16/valix"
)
type MyStruct struct {
Foo struct {
Bar int `json:"bar" v8n:">o{'..baz.qux'}"`
} `json:"foo"`
Baz struct {
Qux int `json:"qux"`
} `json:"baz"`
}
var validator = valix.MustCompileValidatorFor(MyStruct{}, nil)
func main() {
my := &MyStruct{}
ok, violations, _ := validator.ValidateStringInto(`{"foo": {"bar": 1}, "baz": {"qux": 2}}`, my)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
ok, violations, _ = validator.ValidateStringInto(`{"foo": {"bar": 1}, "baz": {"qux": 1}}`, my)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
ok, violations, _ = validator.ValidateStringInto(`{"foo": {"bar": 2}, "baz": {"qux": 1}}`, my)
fmt.Printf("Passed? %v\n", ok)
for i, v := range violations {
fmt.Printf("Violation[%d] Message: %s, Property: %s, Path: %s\n", i+1, v.Message, v.Property, v.Path)
}
}