Merge pull request #571 from psampaz/json

Add isJSON validation
pull/575/head
Dean Karn 5 years ago committed by GitHub
commit b7430f8e39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      baked_in.go
  2. 6
      doc.go
  3. 5
      translations/en/en.go
  4. 5
      translations/en/en_test.go
  5. 50
      validator_test.go

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"context" "context"
"crypto/sha256" "crypto/sha256"
"encoding/json"
"fmt" "fmt"
"net" "net"
"net/url" "net/url"
@ -166,6 +167,7 @@ var (
"html_encoded": isHTMLEncoded, "html_encoded": isHTMLEncoded,
"url_encoded": isURLEncoded, "url_encoded": isURLEncoded,
"dir": isDir, "dir": isDir,
"json": isJSON,
"hostname_port": isHostnamePort, "hostname_port": isHostnamePort,
"lowercase": isLowercase, "lowercase": isLowercase,
"uppercase": isUppercase, "uppercase": isUppercase,
@ -2011,6 +2013,17 @@ func isDir(fl FieldLevel) bool {
panic(fmt.Sprintf("Bad field type %T", field.Interface())) panic(fmt.Sprintf("Bad field type %T", field.Interface()))
} }
// isJSON is the validation function for validating if the current field's value is a valid json string.
func isJSON(fl FieldLevel) bool {
field := fl.Field()
if field.Kind() == reflect.String {
val := field.String()
return json.Valid([]byte(val))
}
panic(fmt.Sprintf("Bad field type %T", field.Interface()))
}
// isHostnamePort validates a <dns>:<port> combination for fields typically used for socket address. // isHostnamePort validates a <dns>:<port> combination for fields typically used for socket address.
func isHostnamePort(fl FieldLevel) bool { func isHostnamePort(fl FieldLevel) bool {
val := fl.Field().String() val := fl.Field().String()

@ -685,6 +685,12 @@ does any email provider accept all possibilities.
Usage: email Usage: email
JSON String
This validates that a string value is valid JSON
Usage: json
File path File path
This validates that a string value contains a valid file path and that This validates that a string value contains a valid file path and that

@ -1322,6 +1322,11 @@ func RegisterDefaultTranslations(v *validator.Validate, trans ut.Translator) (er
}, },
}, },
{ {
tag: "json",
translation: "{0} must be a valid json string",
override: false,
},
{
tag: "lowercase", tag: "lowercase",
translation: "{0} must be a lowercase string", translation: "{0} must be a lowercase string",
override: false, override: false,

@ -141,6 +141,7 @@ func TestTranslations(t *testing.T) {
UniqueSlice []string `validate:"unique"` UniqueSlice []string `validate:"unique"`
UniqueArray [3]string `validate:"unique"` UniqueArray [3]string `validate:"unique"`
UniqueMap map[string]string `validate:"unique"` UniqueMap map[string]string `validate:"unique"`
JSONString string `validate:"json"`
LowercaseString string `validate:"lowercase"` LowercaseString string `validate:"lowercase"`
UppercaseString string `validate:"uppercase"` UppercaseString string `validate:"uppercase"`
} }
@ -637,6 +638,10 @@ func TestTranslations(t *testing.T) {
ns: "Test.UniqueMap", ns: "Test.UniqueMap",
expected: "UniqueMap must contain unique values", expected: "UniqueMap must contain unique values",
}, },
{
ns: "Test.JSONString",
expected: "JSONString must be a valid json string",
},
{ {
ns: "Test.LowercaseString", ns: "Test.LowercaseString",
expected: "LowercaseString must be a lowercase string", expected: "LowercaseString must be a lowercase string",

@ -9004,6 +9004,54 @@ func TestGetTag(t *testing.T) {
Equal(t, tag, "mytag") Equal(t, tag, "mytag")
} }
func TestJSONValidation(t *testing.T) {
tests := []struct {
param string
expected bool
}{
{`foo`, false},
{`}{`, false},
{`{]`, false},
{`{}`, true},
{`{"foo":"bar"}`, true},
{`{"foo":"bar","bar":{"baz":["qux"]}}`, true},
{`{"foo": 3 "bar": 4}`, false},
{`{"foo": 3 ,"bar": 4`, false},
{`{foo": 3, "bar": 4}`, false},
{`foo`, false},
{`1`, true},
{`true`, true},
{`null`, true},
{`"null"`, true},
}
validate := New()
for i, test := range tests {
errs := validate.Var(test.param, "json")
if test.expected {
if !IsEqual(errs, nil) {
t.Fatalf("Index: %d json failed Error: %s", i, errs)
}
} else {
if IsEqual(errs, nil) {
t.Fatalf("Index: %d json failed Error: %s", i, errs)
} else {
val := getError(errs, "", "")
if val.Tag() != "json" {
t.Fatalf("Index: %d json failed Error: %s", i, errs)
}
}
}
}
PanicMatches(t, func() {
_ = validate.Var(2, "json")
}, "Bad field type int")
}
func Test_hostnameport_validator(t *testing.T) { func Test_hostnameport_validator(t *testing.T) {
type Host struct { type Host struct {
@ -9107,4 +9155,4 @@ func TestUppercaseValidation(t *testing.T) {
PanicMatches(t, func() { PanicMatches(t, func() {
_ = validate.Var(2, "uppercase") _ = validate.Var(2, "uppercase")
}, "Bad field type int") }, "Bad field type int")
} }
Loading…
Cancel
Save