Closed tpoxa closed 1 year ago
There is an InterceptType
option that allows schema customization based on its reflect.Value
.
(All available options are listed at https://pkg.go.dev/github.com/swaggest/jsonschema-go#Reflector.Reflect)
https://go.dev/play/p/hZgF5vsks1R
package main
import (
"encoding/json"
"fmt"
"reflect"
"github.com/swaggest/jsonschema-go"
)
func main() {
type CustomParameter interface{}
// User is used as a base to provide tests for comments.
type User struct {
Param interface{} `json:"param" title:"Param"`
// Unique sequential identifier.
// Name of the user
Dynamic CustomParameter `json:"dynamic" title:"Test"`
//Some interface{} `json:"some,omitempty" jsonschema_extras:"requiredWhen=[1,2,3]"`
}
r := jsonschema.Reflector{}
defs := map[string]jsonschema.Schema{}
r.DefaultOptions = append(r.DefaultOptions,
jsonschema.DefinitionsPrefix("#/$defs/"),
jsonschema.CollectDefinitions(func(name string, schema jsonschema.Schema) {
defs[name] = schema
}),
jsonschema.InterceptType(func(value reflect.Value, schema *jsonschema.Schema) (bool, error) {
r := value.Type()
// Nil interfaces arrive as pointer wraps.
if r.Kind() == reflect.Ptr {
r = r.Elem()
}
if r.Name() == "" {
return false, nil
}
if r.Kind() == reflect.Interface {
// Making new definition.
s := jsonschema.Schema{}
s.AddType(jsonschema.Object)
s.WithExtraPropertiesItem("configurable", true)
defs[r.Name()] = s
// Replacing current schema with reference.
rs := jsonschema.Schema{}
rs.WithRef(fmt.Sprintf("#/$defs/%s", r.Name()))
*schema = rs
// Alternatively, in this case schema can be updated instead of replacing,
// because it would be empty for an interface.
//
//schema.WithRef(fmt.Sprintf("#/$defs/%s", r.Name()))
// True return disables further schema processing.
return true, nil
}
return false, nil
}))
sh, _ := r.Reflect(User{})
sh.WithExtraPropertiesItem("$defs", defs)
j, _ := json.MarshalIndent(sh, "", " ")
fmt.Println(string(j))
}
{
"properties": {
"dynamic": {
"$ref": "#/$defs/CustomParameter",
"title": "Test"
},
"param": {
"title": "Param"
}
},
"type": "object",
"$defs": {
"CustomParameter": {
"type": "object",
"configurable": true
}
}
}
That's awesome. Thanks @vearutop
Hey. I am really want to migrate to your library cause it has so much perks but I think I am missing some kind of a Reflector's callback which will allow to generate Schema depends on a
reflect.Type
of a variable.I saw map of types associations but unfortunately it is not an option, cause I do custom types based on a type
any
which I check using.Kind
in the callback. So reflector does not know about exact name of a type.CollectionDefinitions could be option but it gets definition name and schema.
What other thing I can try with?
Here is the program based on
invopop
's library which I am trying to migrate from.The result. I highlighted important points for me
Thank you.