Skip to content

Instantly share code, notes, and snippets.

@billinghamj
Created September 22, 2023 14:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save billinghamj/007a3a2026b487afd83ef9f15f78294a to your computer and use it in GitHub Desktop.
Save billinghamj/007a3a2026b487afd83ef9f15f78294a to your computer and use it in GitHub Desktop.
package polymorphism
type Type interface{ ~string }
type Base[TType Type] interface {
GetType() TType
SetType(TType)
}
type Params[TType Type] interface {
GetType() TType
}
type Outer[TType Type, TBase Base[TType], TParams any] struct {
typeMap map[TType]TParams
Base TBase
Params TParams `json:"params"`
}
func Unmarshal[TType Type, TBase Base[TType], TParams any](data []byte, typeMap map[TType]TParams) (Outer[TType, TBase, TParams], error) {
var o Outer[TType, TBase, TParams]
o.typeMap = typeMap
return o, json.Unmarshal(data, &o)
}
func (o Outer[TType, TBase, TParams]) MarshalJSON() ([]byte, error) {
base, err := json.Marshal(o.Base)
if err != nil {
return nil, err
}
res := map[string]any{}
if err := json.Unmarshal(base, &res); err != nil {
return nil, err
}
res["params"] = o.Params
return json.Marshal(res)
}
func (o *Outer[TType, TBase, TParams]) UnmarshalJSON(data []byte) error {
var base TBase
if err := json.Unmarshal(data, &base); err != nil {
return err
}
var paramsWrapper struct {
Params json.RawMessage `json:"params"`
}
if err := json.Unmarshal(data, &paramsWrapper); err != nil {
return err
}
typ := base.GetType()
paramsType, ok := o.typeMap[typ]
if !ok {
return cher.New("unknown_event_type", cher.M{"type": typ})
}
params := reflect.New(reflect.TypeOf(paramsType)).Interface().(TParams)
if err := json.Unmarshal(paramsWrapper.Params, &params); err != nil {
return err
}
*o = Outer[TType, TBase, TParams]{
Base: base,
Params: params,
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment