Support getting underlying value from oneOf type
Description
When you define a oneOf type that has shared fields (e.g. ID) and you want to access this field, regardless of the underlying type, you need to perform a switch. If we had a method to return the underlying type as an interface it would make code less brittle as a new type being added to the spec would not need the switch to be updated in these circumstances.
See the example below:
description: Anything
oneOf:
- $ref: ./Foo.yaml
- $ref: ./Bar.yaml
- $ref: ./Baz.yaml
discriminator:
propertyName: type
mapping:
Foo: ./Foo.yaml
Bar: ./Bar.yaml
Baz: ./Baz.yaml
type Anything struct {
Type AnythingType // switch on this field
Foo Foo
Bar Bar
Baz Baz
}
// This is the method I'd like to see generated.
func (a Anything) GetValue() any {
switch a.Type {
case FooAnything:
return a.Foo
case BarAnything:
return a.Bar
case BazAnything:
return a.Baz
default:
return nil
}
}
This would allow code like this:
type GetIDer interface {
GetID int64
}
func getID(a Anything) int64 {
if v, ok := a.GetValue().(GetIDer); ok {
return v.GetID()
}
return 0
}
Right now we cannot get around being very explicit such as the example below, with the added issue of it breaking if another type is added to the spec.
func getID(a Anything) int64 {
switch a.Type {
case FooAnything:
return a.Foo.ID
case BarAnything:
return a.Bar.ID
case BazAnything:
return a.Baz.ID
default:
return 0
}
}
References
Could you do something like this?
func getID(r ResponseType) int64 {
g, ok := r.(interface{ GetID() int64 })
if ok { return g.GetID() }
return 0
}
No because the ID prop is on the respective types (Foo, Bar and Baz in the example above) so it still requires a switch on the type property. That's why my suggestion is to implement a function on each oneOf type to get the set value. This is fairly simple to implement in the generator templates.
Perhaps one way to support this could be to simplify the scope of the work, and support "output only" generation (encoder, response, ...)?
This way, there would be no need to identity discriminator for decoding.
I think it would be much simpler to just add another method to the generated sum types. I could easily implement that but was hoping for feedback from the maintainers first.