invopop / jsonschema

Generate JSON Schemas from Go types
MIT License
511 stars 86 forks source link

name generation of generic types #131

Open olistrik opened 8 months ago

olistrik commented 8 months ago

Is it possible to customise how the names of generic references are generated?

If I have for example the following:

type Foo int
type Bar int

type FooMap[T any] map[Foo]T

type struct FooBar {
  FooBar FooMap[Bar]
}

The resulting $ref for the FooBar $def is FooMap[github.com/full/path/to/package.Bar].

I'd like to change this to FooMap[Bar].

joshstrohminger commented 7 months ago

I wonder if this will be easier once Go exposes the generic child type via reflection, but for now I've been solving this with a recursive namer. I'm not sure what other types like arrays, maps, or slices show up as though.

var genericTypeRegex = regexp.MustCompile(`^(.+?)\[(.+)]$`)

func getSimpleTypeName(name string) string {
    parts := strings.Split(name, ".")
    return parts[len(parts)-1]
}

func getGenericName(name string) string {
    if matches := genericTypeRegex.FindStringSubmatch(name); matches != nil {
        parent := getSimpleTypeName(matches[1])
        child := getGenericName(matches[2])
        return fmt.Sprintf("%s[%s]", parent, child)
    }
    return getSimpleTypeName(name)
}

func nameGenerics(r reflect.Type) string {
    return getGenericName(r.Name())
}

and then use it like

reflector := jsonschema.Reflector{ Namer: nameGenerics }
s := reflector.Reflect(myType)
samlown commented 7 months ago

If you'd like to add some broken tests for this, it'd be easier to have a look and align expectations. Generics were not available when this library was first built!