Skip to content

Commit

Permalink
feat(reflect): Add method to modify the schema after processing
Browse files Browse the repository at this point in the history
  • Loading branch information
webdestroya committed Oct 9, 2022
1 parent 679d2eb commit bd9a931
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 0 deletions.
23 changes: 23 additions & 0 deletions fixtures/custom_type_post.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://github.com/invopop/jsonschema/schema-post-test",
"$ref": "#/$defs/SchemaPostTest",
"$defs": {
"SchemaPostTest": {
"properties": {
"LastName": {
"type": "string",
"description": "some extra words"
},
"middle_name": {
"type": "string"
}
},
"additionalProperties": false,
"type": "object",
"required": [
"LastName"
]
}
}
}
22 changes: 22 additions & 0 deletions reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,14 @@ type customSchemaImpl interface {
JSONSchema() *Schema
}

// Function to be run after the schema has been generated.
// this will let you modify a schema afterwards
type postSchemaImpl interface {
JSONSchemaPost(*Schema)
}

var customType = reflect.TypeOf((*customSchemaImpl)(nil)).Elem()
var postType = reflect.TypeOf((*postSchemaImpl)(nil)).Elem()

// customSchemaGetFieldDocString
type customSchemaGetFieldDocString interface {
Expand Down Expand Up @@ -395,6 +402,8 @@ func (r *Reflector) reflectTypeToSchema(definitions Definitions, t reflect.Type)
panic("unsupported type " + t.String())
}

r.reflectSchemaPost(definitions, t, st)

// Always try to reference the definition which may have just been created
if def := r.refDefinition(definitions, t); def != nil {
return def
Expand Down Expand Up @@ -422,6 +431,19 @@ func (r *Reflector) reflectCustomSchema(definitions Definitions, t reflect.Type)
return nil
}

func (r *Reflector) reflectSchemaPost(definitions Definitions, t reflect.Type, s *Schema) *Schema {
if t.Implements(postType) {
v := reflect.New(t)
o := v.Interface().(postSchemaImpl)
o.JSONSchemaPost(s)
if ref := r.refDefinition(definitions, t); ref != nil {
return ref
}
}

return s
}

func (r *Reflector) reflectSliceOrArray(definitions Definitions, t reflect.Type, st *Schema) {
if t == rawMessageType {
return
Expand Down
20 changes: 20 additions & 0 deletions reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,25 @@ type KeyNamed struct {
RenamedByComputation int `jsonschema_description:"Description was preserved"`
}

type SchemaPostTestBase struct {
FirstName string `json:"FirstName"`
LastName string `json:"LastName"`
Age uint `json:"age"`
MiddleName string `json:"middle_name,omitempty"`
}

type SchemaPostTest struct {
SchemaPostTestBase `json:",inline"`
}

func (SchemaPostTest) JSONSchemaPost(base *Schema) {
base.Properties.Delete("FirstName")
base.Properties.Delete("age")
val, _ := base.Properties.Get("LastName")
(val).(*Schema).Description = "some extra words"
base.Required = []string{"LastName"}
}

func TestReflector(t *testing.T) {
r := new(Reflector)
s := "http://example.com/schema"
Expand Down Expand Up @@ -424,6 +443,7 @@ func TestSchemaGeneration(t *testing.T) {
}, "fixtures/keynamed.json"},
{MapType{}, &Reflector{}, "fixtures/map_type.json"},
{ArrayType{}, &Reflector{}, "fixtures/array_type.json"},
{SchemaPostTest{}, &Reflector{}, "fixtures/custom_type_post.json"},
}

for _, tt := range tests {
Expand Down

0 comments on commit bd9a931

Please sign in to comment.