fix: Custom typePath function instead of exposing private `jsonschema.typePath` function

This commit is contained in:
Ilya Kuznetsov 2024-12-09 16:23:02 +01:00
parent 79a88e945f
commit c3d049f3e5
No known key found for this signature in database
GPG Key ID: 91F3DDCF5D21CDDF
4 changed files with 15 additions and 11 deletions

View File

@ -64,7 +64,7 @@ func newAnnotationHandler(sources []string) (*annotationHandler, error) {
} }
func (d *annotationHandler) addAnnotations(typ reflect.Type, s jsonschema.Schema) jsonschema.Schema { func (d *annotationHandler) addAnnotations(typ reflect.Type, s jsonschema.Schema) jsonschema.Schema {
refPath := jsonschema.TypePath(typ) refPath := getPath(typ)
items := map[string]*jsonschema.Schema{} items := map[string]*jsonschema.Schema{}
items[refPath] = &s items[refPath] = &s
@ -128,3 +128,7 @@ func (d *annotationHandler) sync(outputPath string) error {
} }
return nil return nil
} }
func getPath(typ reflect.Type) string {
return typ.PkgPath() + "." + typ.Name()
}

View File

@ -115,7 +115,7 @@ func (p *openapiParser) extractAnnotations(typ reflect.Type, outputPath, overrid
return s return s
} }
basePath := jsonschema.TypePath(typ) basePath := getPath(typ)
annotations[basePath] = annotation{ annotations[basePath] = annotation{
Description: ref.Description, Description: ref.Description,
Enum: ref.Enum, Enum: ref.Enum,

View File

@ -52,7 +52,7 @@ func (c *constructor) Definitions() map[string]any {
// Remove the root type from the definitions. We don't need to include it in // Remove the root type from the definitions. We don't need to include it in
// the definitions because it will be inlined as the root of the generated JSON schema. // the definitions because it will be inlined as the root of the generated JSON schema.
delete(defs, TypePath(c.root)) delete(defs, typePath(c.root))
if len(defs) == 0 { if len(defs) == 0 {
return nil return nil
@ -106,14 +106,14 @@ func FromType(typ reflect.Type, fns []func(typ reflect.Type, s Schema) Schema) (
} }
} }
res := c.definitions[TypePath(typ)] res := c.definitions[typePath(typ)]
res.Definitions = c.Definitions() res.Definitions = c.Definitions()
return res, nil return res, nil
} }
// TypePath computes a unique string representation of the type. $ref in the generated // typePath computes a unique string representation of the type. $ref in the generated
// JSON schema will refer to this path. See TestTypePath for examples outputs. // JSON schema will refer to this path. See TestTypePath for examples outputs.
func TypePath(typ reflect.Type) string { func typePath(typ reflect.Type) string {
// Pointers have a typ.Name() of "". Dereference them to get the underlying type. // Pointers have a typ.Name() of "". Dereference them to get the underlying type.
for typ.Kind() == reflect.Ptr { for typ.Kind() == reflect.Ptr {
typ = typ.Elem() typ = typ.Elem()
@ -125,7 +125,7 @@ func TypePath(typ reflect.Type) string {
// Recursively call typePath, to handle slices of slices / maps. // Recursively call typePath, to handle slices of slices / maps.
if typ.Kind() == reflect.Slice { if typ.Kind() == reflect.Slice {
return path.Join("slice", TypePath(typ.Elem())) return path.Join("slice", typePath(typ.Elem()))
} }
if typ.Kind() == reflect.Map { if typ.Kind() == reflect.Map {
@ -134,7 +134,7 @@ func TypePath(typ reflect.Type) string {
} }
// Recursively call typePath, to handle maps of maps / slices. // Recursively call typePath, to handle maps of maps / slices.
return path.Join("map", TypePath(typ.Elem())) return path.Join("map", typePath(typ.Elem()))
} }
switch { switch {
@ -157,7 +157,7 @@ func (c *constructor) walk(typ reflect.Type) (string, error) {
typ = typ.Elem() typ = typ.Elem()
} }
typPath := TypePath(typ) typPath := typePath(typ)
// Return early if the type has already been seen, to avoid infinite recursion. // Return early if the type has already been seen, to avoid infinite recursion.
if _, ok := c.seen[typPath]; ok { if _, ok := c.seen[typPath]; ok {

View File

@ -510,12 +510,12 @@ func TestTypePath(t *testing.T) {
for _, tc := range tcases { for _, tc := range tcases {
t.Run(tc.typ.String(), func(t *testing.T) { t.Run(tc.typ.String(), func(t *testing.T) {
assert.Equal(t, tc.path, TypePath(tc.typ)) assert.Equal(t, tc.path, typePath(tc.typ))
}) })
} }
// Maps with non-string keys should panic. // Maps with non-string keys should panic.
assert.PanicsWithValue(t, "found map with non-string key: int", func() { assert.PanicsWithValue(t, "found map with non-string key: int", func() {
TypePath(reflect.TypeOf(map[int]int{})) typePath(reflect.TypeOf(map[int]int{}))
}) })
} }