Skip to content

Commit

Permalink
openapi3gen: allow overriding how a Schema is generated (#920)
Browse files Browse the repository at this point in the history
* openapi3gen: adds custom schema definition for client implementing our interface

* Add Unitest and trigger docs.sh (#1)

* add unitest, generate docs

* test: change test setschema to example

---------

Co-authored-by: Taufik Rama <[email protected]>
Co-authored-by: Ferianto Surya Wijaya <[email protected]>
Co-authored-by: blackhun11 <[email protected]>
  • Loading branch information
4 people authored Apr 6, 2024
1 parent 78bb273 commit 5aee5fc
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .github/docs/openapi3gen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,10 @@ type SchemaCustomizerFn func(name string, t reflect.Type, tag reflect.StructTag,
A SchemaCustomizerFn can return an ExcludeSchemaSentinel error to indicate
that the schema for this field should not be included in the final output

type SetSchemar interface {
SetSchema(*openapi3.Schema)
}
SetSchemar allows client to set their own schema definition according to
their specification. Useful when some custom datatype is needed and/or some
custom logic is needed on how the schema values would be generated

15 changes: 15 additions & 0 deletions openapi3gen/openapi3gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ type Option func(*generatorOpt)
// the final output
type SchemaCustomizerFn func(name string, t reflect.Type, tag reflect.StructTag, schema *openapi3.Schema) error

// SetSchemar allows client to set their own schema definition according to
// their specification. Useful when some custom datatype is needed and/or some custom logic
// is needed on how the schema values would be generated
type SetSchemar interface {
SetSchema(*openapi3.Schema)
}

type generatorOpt struct {
useAllExportedFields bool
throwErrorOnCycle bool
Expand Down Expand Up @@ -347,6 +354,14 @@ func (g *Generator) generateWithoutSaving(parents []*theTypeInfo, t reflect.Type
schema.Type = &openapi3.Types{"object"}
}
}

default:
// Object has their own schema's implementation, so we'll use those
if v := reflect.New(t); v.CanInterface() {
if v, ok := v.Interface().(SetSchemar); ok {
v.SetSchema(schema)
}
}
}

if g.opts.schemaCustomizer != nil {
Expand Down
40 changes: 40 additions & 0 deletions openapi3gen/openapi3gen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -590,3 +590,43 @@ func ExampleNewSchemaRefForValue_recursive() {
// "type": "object"
// }
}

type ID [16]byte

// T implements SetSchemar, allowing it to set an OpenAPI schema.
type T struct {
ID ID `json:"id"`
}

func (_ *ID) SetSchema(schema *openapi3.Schema) {
schema.Type = &openapi3.Types{"string"} // Assuming this matches your custom implementation
schema.Format = "uuid"
}

func ExampleID_SetSchema() {
schemas := make(openapi3.Schemas)
instance := &T{
ID: ID{},
}

// Generate the schema for the instance
schemaRef, err := openapi3gen.NewSchemaRefForValue(instance, schemas)
if err != nil {
panic(err)
}
data, err := json.MarshalIndent(schemaRef, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("schemaRef: %s\n", data)
// Output:
// schemaRef: {
// "properties": {
// "id": {
// "format": "uuid",
// "type": "string"
// }
// },
// "type": "object"
// }
}

0 comments on commit 5aee5fc

Please sign in to comment.