oto
oto copied to clipboard
Support polymorphic unmarshaling
I want to support polymophic discrimination through serialization. For example, see this short example:
package main
import (
"encoding/json"
"fmt"
)
type FruitType string
const (
AppleType FruitType = "Apple"
BananaType FruitType = "Banana"
)
type Fruit interface {
Type() FruitType
}
type fruitWrapper struct {
Type FruitType `json:"type"`
}
type Apple struct {
Type FruitType `json:"type"`
Variety string `json:"variety"`
}
func (Apple) Type() FruitType { return AppleType }
type Banana struct {
Type FruitType `json:"type"`
Length int `json:"length"`
}
func (Banana) Type() FruitType { return BananaType }
func (f *Fruit) UnmarshalJSON(data []byte) error {
var wrapper fruitWrapper
if err := json.Unmarshal(data, &wrapper); err != nil {
return err
}
switch wrapper.Type {
case AppleType:
var apple Apple
if err := json.Unmarshal(data, &apple); err != nil {
return err
}
*f = apple
case BananaType:
var banana Banana
if err := json.Unmarshal(data, &banana); err != nil {
return err
}
*f = banana
default:
return fmt.Errorf("unknown type")
}
return nil
}
func main() {
jsonData := []byte(`{"type":"Apple","variety":"Fuji"}`)
var fruit Fruit
if err := json.Unmarshal(jsonData, &fruit); err != nil {
fmt.Println(err)
return
}
switch f := fruit.(type) {
case Apple:
fmt.Println("Apple variety:", f.Variety)
case Banana:
fmt.Println("Banana length:", f.Length)
default:
fmt.Println("Unknown fruit")
}
}
To support this in oto, I suppose this function needs to support conditional unmarshalling, as above. To get correct TS code generation, we'd need to have all of the defined interfaces/structs tied together somehow, too.
Perhaps in the def, something like this:
type User interface {
// specializations: SpecificUser, AltUser, SomeOtherUserType
Type() UserType
}
...
// specializationOf: User
type SpecificUser struct {
then some mechanism to emit the correct code. I wonder at what the right level of codegen vs explicit specification is right, especially as Oto has the need to build these up in templates, too.