From 1ec8c24ea7ae0e31d5e8332f8a0349d2ecd5b913 Mon Sep 17 00:00:00 2001 From: Wei-An Yen Date: Sat, 21 Sep 2024 02:22:01 +0800 Subject: [PATCH] fix: jsonschema integer validation (#852) --- jsonschema/validate.go | 4 ++++ jsonschema/validate_test.go | 48 +++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/jsonschema/validate.go b/jsonschema/validate.go index f14ffd4c..49f9b885 100644 --- a/jsonschema/validate.go +++ b/jsonschema/validate.go @@ -36,6 +36,10 @@ func Validate(schema Definition, data any) bool { _, ok := data.(bool) return ok case Integer: + // Golang unmarshals all numbers as float64, so we need to check if the float64 is an integer + if num, ok := data.(float64); ok { + return num == float64(int64(num)) + } _, ok := data.(int) return ok case Null: diff --git a/jsonschema/validate_test.go b/jsonschema/validate_test.go index c2c47a2c..6fa30ab0 100644 --- a/jsonschema/validate_test.go +++ b/jsonschema/validate_test.go @@ -86,14 +86,6 @@ func TestUnmarshal(t *testing.T) { content []byte v any } - var result1 struct { - String string `json:"string"` - Number float64 `json:"number"` - } - var result2 struct { - String string `json:"string"` - Number float64 `json:"number"` - } tests := []struct { name string args args @@ -108,7 +100,10 @@ func TestUnmarshal(t *testing.T) { }, }, content: []byte(`{"string":"abc","number":123.4}`), - v: &result1, + v: &struct { + String string `json:"string"` + Number float64 `json:"number"` + }{}, }, false}, {"", args{ schema: jsonschema.Definition{ @@ -120,7 +115,40 @@ func TestUnmarshal(t *testing.T) { Required: []string{"string", "number"}, }, content: []byte(`{"string":"abc"}`), - v: result2, + v: struct { + String string `json:"string"` + Number float64 `json:"number"` + }{}, + }, true}, + {"validate integer", args{ + schema: jsonschema.Definition{ + Type: jsonschema.Object, + Properties: map[string]jsonschema.Definition{ + "string": {Type: jsonschema.String}, + "integer": {Type: jsonschema.Integer}, + }, + Required: []string{"string", "integer"}, + }, + content: []byte(`{"string":"abc","integer":123}`), + v: &struct { + String string `json:"string"` + Integer int `json:"integer"` + }{}, + }, false}, + {"validate integer failed", args{ + schema: jsonschema.Definition{ + Type: jsonschema.Object, + Properties: map[string]jsonschema.Definition{ + "string": {Type: jsonschema.String}, + "integer": {Type: jsonschema.Integer}, + }, + Required: []string{"string", "integer"}, + }, + content: []byte(`{"string":"abc","integer":123.4}`), + v: &struct { + String string `json:"string"` + Integer int `json:"integer"` + }{}, }, true}, } for _, tt := range tests {