From c1722b720fafa56f0514e08063b5a3c6baa73863 Mon Sep 17 00:00:00 2001 From: Arvydas Sidorenko Date: Sat, 24 Aug 2019 16:00:04 +0200 Subject: [PATCH] feat(type): identify custom struct as objects Limiting type `object` to `map[string]interface{}` and nothing else is restrictive. Since the library allows to pass data structures as input, some of it can contain user defined data structures and we shall be able to identify them as `object` instead of `unknown`. --- keywords.go | 19 +++++++++++-------- schema_test.go | 11 +++++++++-- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/keywords.go b/keywords.go index 66c5eb5..f8467ad 100644 --- a/keywords.go +++ b/keywords.go @@ -22,21 +22,24 @@ var primitiveTypes = map[string]bool{ // DataType gives the primitive json type of a standard json-decoded value, plus the special case // "integer" for when numbers are whole func DataType(data interface{}) string { - switch v := data.(type) { - case nil: + if data == nil { return "null" - case bool: + } + + switch reflect.TypeOf(data).Kind() { + case reflect.Bool: return "boolean" - case float64: - if float64(int(v)) == v { + case reflect.Float64: + number := reflect.ValueOf(data).Float() + if float64(int(number)) == number { return "integer" } return "number" - case string: + case reflect.String: return "string" - case []interface{}: + case reflect.Array, reflect.Slice: return "array" - case map[string]interface{}: + case reflect.Map, reflect.Struct: return "object" default: return "unknown" diff --git a/schema_test.go b/schema_test.go index cecad8d..32dfed7 100644 --- a/schema_test.go +++ b/schema_test.go @@ -449,17 +449,24 @@ func runJSONTests(t *testing.T, testFilepaths []string) { } func TestDataType(t *testing.T) { + type customObject struct {} + type customNumber float64 + cases := []struct { data interface{} expect string }{ {nil, "null"}, - {struct{}{}, "unknown"}, {float64(4), "integer"}, {float64(4.5), "number"}, + {customNumber(4.5), "number"}, {"foo", "string"}, - {map[string]interface{}{}, "object"}, {[]interface{}{}, "array"}, + {[0]interface{}{}, "array"}, + {map[string]interface{}{}, "object"}, + {struct{}{}, "object"}, + {customObject{}, "object"}, + {int8(42), "unknown"}, } for i, c := range cases {