Repository: go-playground/validator
Pull request #1110 (2023-05-25 07:09:24)

allow byte slice and json raw message in IsJson
## Fixes Or Enhances

* json.RawMessage and []byte can be validated as JSON 

**Make sure that you've checked the boxes below before you submit PR:**
- [x] Tests exist or have been written that cover this particular change.

@go-playground/validator-maintainers

coveralls: 
[![Coverage Status](https://coveralls.io/builds/60300847/badge)](https://coveralls.io/builds/60300847)

Coverage: 73.951% (-0.007%) from 73.958% when pulling **fe8921b56f92e1bc0567d599b7a0b3ca338f1bfa on Vesquen:feat-json-raw-message-and-byte-slice-support** into **ce28d7c4b27fbcafff82bc87a8bf58257beb9030 on go-playground:master**.


Patch:
diff --git a/baked_in.go b/baked_in.go
index 8e6b169..82162e9 100644
--- a/baked_in.go
+++ b/baked_in.go
@@ -2568,9 +2568,17 @@ func isDirPath(fl FieldLevel) bool {
 func isJSON(fl FieldLevel) bool {
 	field := fl.Field()
 
-	if field.Kind() == reflect.String {
+	switch field.Kind() {
+	case reflect.String:
 		val := field.String()
 		return json.Valid([]byte(val))
+	case reflect.Slice:
+		fieldType := field.Type()
+
+		if fieldType.ConvertibleTo(byteSliceType) {
+			b := field.Convert(byteSliceType).Interface().([]byte)
+			return json.Valid(b)
+		}
 	}
 
 	panic(fmt.Sprintf("Bad field type %T", field.Interface()))
diff --git a/validator_instance.go b/validator_instance.go
index d2ee8fe..d9dbf0c 100644
--- a/validator_instance.go
+++ b/validator_instance.go
@@ -53,6 +53,8 @@ var (
 	timeDurationType = reflect.TypeOf(time.Duration(0))
 	timeType         = reflect.TypeOf(time.Time{})
 
+	byteSliceType = reflect.TypeOf([]byte{})
+
 	defaultCField = &cField{namesEqual: true}
 )
 


Test patch:
diff --git a/validator_test.go b/validator_test.go
index a60e4bc..9fbc41c 100644
--- a/validator_test.go
+++ b/validator_test.go
@@ -11958,7 +11958,7 @@ func TestGetTag(t *testing.T) {
 
 func TestJSONValidation(t *testing.T) {
 	tests := []struct {
-		param    string
+		param    interface{}
 		expected bool
 	}{
 		{`foo`, false},
@@ -11975,6 +11975,34 @@ func TestJSONValidation(t *testing.T) {
 		{`true`, true},
 		{`null`, true},
 		{`"null"`, true},
+		{json.RawMessage(`foo`), false},
+		{json.RawMessage(`}{`), false},
+		{json.RawMessage(`{]`), false},
+		{json.RawMessage(`{}`), true},
+		{json.RawMessage(`{"foo":"bar"}`), true},
+		{json.RawMessage(`{"foo":"bar","bar":{"baz":["qux"]}}`), true},
+		{json.RawMessage(`{"foo": 3 "bar": 4}`), false},
+		{json.RawMessage(`{"foo": 3 ,"bar": 4`), false},
+		{json.RawMessage(`{foo": 3, "bar": 4}`), false},
+		{json.RawMessage(`foo`), false},
+		{json.RawMessage(`1`), true},
+		{json.RawMessage(`true`), true},
+		{json.RawMessage(`null`), true},
+		{json.RawMessage(`"null"`), true},
+		{[]byte(`foo`), false},
+		{[]byte(`}{`), false},
+		{[]byte(`{]`), false},
+		{[]byte(`{}`), true},
+		{[]byte(`{"foo":"bar"}`), true},
+		{[]byte(`{"foo":"bar","bar":{"baz":["qux"]}}`), true},
+		{[]byte(`{"foo": 3 "bar": 4}`), false},
+		{[]byte(`{"foo": 3 ,"bar": 4`), false},
+		{[]byte(`{foo": 3, "bar": 4}`), false},
+		{[]byte(`foo`), false},
+		{[]byte(`1`), true},
+		{[]byte(`true`), true},
+		{[]byte(`null`), true},
+		{[]byte(`"null"`), true},
 	}
 
 	validate := New()