Skip to content

Commit e08864c

Browse files
authored
make struct validation fail (#28)
Validating directly against a struct has problems (see #23). We could marshal it to JSON and then unmarshal to a map[string]any, but that is a performance footgun. Have it fail for now. We can add it back later if we choose to. For #23.
1 parent 7da386c commit e08864c

File tree

2 files changed

+14
-11
lines changed

2 files changed

+14
-11
lines changed

jsonschema/validate.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package jsonschema
66

77
import (
88
"encoding/json"
9+
"errors"
910
"fmt"
1011
"hash/maphash"
1112
"iter"
@@ -399,11 +400,13 @@ func (st *state) validate(instance reflect.Value, schema *Schema, callerAnns *an
399400

400401
// objects
401402
// https://json-schema.org/draft/2020-12/json-schema-core#section-10.3.2
402-
if instance.Kind() == reflect.Map || instance.Kind() == reflect.Struct {
403-
if instance.Kind() == reflect.Map {
404-
if kt := instance.Type().Key(); kt.Kind() != reflect.String {
405-
return fmt.Errorf("map key type %s is not a string", kt)
406-
}
403+
// Validating structs is problematic. See https://github.com/google/jsonschema-go/issues/23.
404+
if instance.Kind() == reflect.Struct {
405+
return errors.New("cannot validate against a struct; see https://github.com/google/jsonschema-go/issues/23 for details")
406+
}
407+
if instance.Kind() == reflect.Map {
408+
if kt := instance.Type().Key(); kt.Kind() != reflect.String {
409+
return fmt.Errorf("map key type %s is not a string", kt)
407410
}
408411
// Track the evaluated properties for just this schema, to support additionalProperties.
409412
// If we used anns here, then we'd be including properties evaluated in subschemas

jsonschema/validate_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,9 @@ func TestStructInstance(t *testing.T) {
260260
t.Fatal(err)
261261
}
262262
err = res.Validate(instance)
263-
if err == nil && !tt.want {
264-
t.Errorf("succeeded unexpectedly\nschema = %s", tt.s.json())
265-
} else if err != nil && tt.want {
266-
t.Errorf("Validate: %v\nschema = %s", err, tt.s.json())
263+
// Validating a struct always fails.
264+
if err == nil {
265+
t.Error("struct validation succeeded")
267266
}
268267
}
269268
}
@@ -442,8 +441,9 @@ func TestStructEmbedding(t *testing.T) {
442441
t.Fatalf("schema.Resolve() failed: %v", err)
443442
}
444443
// Validate a correct instance against the generated schema.
445-
if err := resolved.Validate(tc.validInstance); err != nil {
446-
t.Errorf("resolved.Validate() failed on a valid instance: %v", err)
444+
// Struct validation always fails.
445+
if err := resolved.Validate(tc.validInstance); err == nil {
446+
t.Error("struct validation succeeded")
447447
}
448448
})
449449
}

0 commit comments

Comments
 (0)