Skip to content

constraint.GreaterThanOther

marrow16 edited this page Jan 21, 2023 · 6 revisions

Prev Home Next

Constraint: GreaterThanOther

Description

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

V8n Tag Abbreviation

gto

Fields

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)

Examples

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)
    }
}

try on go-playground

Struct v8n tag example...
package main

import (
    "fmt"

    "github.com/marrow16/valix"
)

type MyStruct struct {
    Start float64 `json:"start"`
    End   float64 `json:"end" v8n:"&gto{'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)
    }
}

try on go-playground

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:&gto{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
}

try on go-playground

With path traversal...
package main

import (
    "fmt"

    "github.com/marrow16/valix"
)

type MyStruct struct {
    Foo struct {
        Bar int `json:"bar" v8n:"&gto{'..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)
    }
}

try on go-playground

Clone this wiki locally