Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ExcludeSchema sentinel error for schemaCustomizer #522

Merged
merged 2 commits into from
Apr 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion openapi3gen/openapi3gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ type CycleError struct{}

func (err *CycleError) Error() string { return "detected cycle" }

// ExcludeSchemaSentinel indicates that the schema for a specific field should not be included in the final output.
type ExcludeSchemaSentinel struct{}

func (err *ExcludeSchemaSentinel) Error() string { return "schema excluded" }

// Option allows tweaking SchemaRef generation
type Option func(*generatorOpt)

// SchemaCustomizerFn is a callback function, allowing
// the OpenAPI schema definition to be updated with additional
// properties during the generation process, based on the
// name of the field, the Go type, and the struct tags.
// name will be "_root" for the top level object, and tag will be ""
// name will be "_root" for the top level object, and tag will be "".
// A SchemaCustomizerFn can return an ExcludeSchemaSentinel error to
// indicate that the schema for this field should not be included in
// the final output
type SchemaCustomizerFn func(name string, t reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error

type generatorOpt struct {
Expand Down Expand Up @@ -117,6 +125,10 @@ func (g *Generator) generateSchemaRefFor(parents []*jsoninfo.TypeInfo, t reflect
return ref, nil
}
ref, err := g.generateWithoutSaving(parents, t, name, tag)
if _, ok := err.(*ExcludeSchemaSentinel); ok {
// This schema should not be included in the final output
return nil, nil
}
if err != nil {
return nil, err
}
Expand Down
24 changes: 24 additions & 0 deletions openapi3gen/openapi3gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,30 @@ func TestSchemaCustomizerError(t *testing.T) {
require.EqualError(t, err, "test error")
}

func TestSchemaCustomizerExcludeSchema(t *testing.T) {
type Bla struct {
Str string
}

customizer := openapi3gen.SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error {
return nil
})
schema, err := openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields(), customizer)
require.NoError(t, err)
require.Equal(t, &openapi3.SchemaRef{Value: &openapi3.Schema{
Type: "object",
Properties: map[string]*openapi3.SchemaRef{
"Str": {Value: &openapi3.Schema{Type: "string"}},
}}}, schema)

customizer = openapi3gen.SchemaCustomizer(func(name string, ft reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error {
return &openapi3gen.ExcludeSchemaSentinel{}
})
schema, err = openapi3gen.NewSchemaRefForValue(&Bla{}, nil, openapi3gen.UseAllExportedFields(), customizer)
require.NoError(t, err)
require.Nil(t, schema)
}

func ExampleNewSchemaRefForValue_recursive() {
type RecursiveType struct {
Field1 string `json:"field1"`
Expand Down