Skip to content

Commit

Permalink
Allow oneof for any schemas (#105)
Browse files Browse the repository at this point in the history
* Allow oneof for any schemas

* Explicitly allow objects in oneof, and improve docs and tests

* Fix linter error

* Update error message for any type
  • Loading branch information
jaredoconnell authored Dec 10, 2024
1 parent 1c26e77 commit 2c4dbf8
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 6 deletions.
13 changes: 8 additions & 5 deletions schema/any.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,15 @@ func (a *AnySchema) ValidateCompatibility(typeOrData any) error {
case reflect.Map:
return nil
default:
// Check if it's an actual 'any' schema.
schemaType, ok := typeOrData.(*AnySchema)
if !ok {
// It's not an any schema, so error
// Schema is not a primitive, slice, or map type, so check the complex types
// Explicitly allow object schemas since their reflected type can be a struct if they are struct mapped.
switch typeOrData.(type) {
case *AnySchema, *OneOfSchema[int64], *OneOfSchema[string], *ObjectSchema:
// These are the allowed values.
default:
// It's not an any schema or a type compatible with an any schema, so error
return &ConstraintError{
Message: fmt.Sprintf("unsupported schema type for 'any' type: %T", schemaType),
Message: fmt.Sprintf("schema type `%T` cannot be used as an input for an 'any' type", typeOrData),
}
}
return nil
Expand Down
28 changes: 27 additions & 1 deletion schema/any_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,24 @@ func TestAnyTypeReflectedType(t *testing.T) {

func TestAnyValidateCompatibility(t *testing.T) {
s1 := schema.NewAnySchema()
properties := map[string]*schema.PropertySchema{
"field1": schema.NewPropertySchema(
schema.NewIntSchema(nil, nil, nil),
nil,
true,
nil,
nil,
nil,
nil,
nil,
),
}
type someStruct struct {
//nolint:unused // This is just for test purposes.
field1 int
}
objectSchema := schema.NewObjectSchema("some-id", properties)
structMappedObjectSchema := schema.NewStructMappedObjectSchema[someStruct]("some-id", properties)

assert.NoError(t, s1.ValidateCompatibility(schema.NewAnySchema()))
assert.NoError(t, s1.ValidateCompatibility(schema.NewStringSchema(nil, nil, nil)))
Expand All @@ -170,5 +188,13 @@ func TestAnyValidateCompatibility(t *testing.T) {
assert.NoError(t, s1.ValidateCompatibility(map[string]any{}))
assert.NoError(t, s1.ValidateCompatibility(schema.NewStringEnumSchema(map[string]*schema.DisplayValue{})))
assert.NoError(t, s1.ValidateCompatibility(schema.NewIntEnumSchema(map[int64]*schema.DisplayValue{}, nil)))

assert.NoError(t, s1.ValidateCompatibility(objectSchema))
// Test struct mapped since it may have a different reflected type.
assert.NoError(t, s1.ValidateCompatibility(structMappedObjectSchema))
assert.NoError(t, s1.ValidateCompatibility(
schema.NewOneOfStringSchema[string](map[string]schema.Object{}, "id", false),
))
assert.NoError(t, s1.ValidateCompatibility(
schema.NewOneOfIntSchema[int64](map[int64]schema.Object{}, "id", false),
))
}

0 comments on commit 2c4dbf8

Please sign in to comment.