Shuttle Marshal/Unmarshal
It's hard to deserialize bytes to a specified derived struct implements some interfaces.
So you have to write a lot of code to do this.
Referenced and enhanced the idea from prometheus.
Weave like shuttle.
It supports json ,msgpack and yaml now, but generated idl like protobuf, thrift is not supported.
You could see the test cases in test/ folder.
type Flyable interface{
Fly()
}
type Bird struct{
Name string `json:"name"`
}
func (a *Bird) Fly() {
}
type Plane struct{
Num string `json:"num"`
}
func (a *Plane) Fly() {
}
// step 1. register your structs
core.RegisterType("Bird", &Bird{})
core.RegisterType("Plane", &Plane{})
// step 2. modify your struct field tags, add shuttle:",wrap",
// and Implement Marshaler and Unmarshaler of json or yaml
type SomeStructA struct {
F1 Flyable `json:"F1" shuttle:",wrap"`
F2 Flyable `json:"F2", shuttle:",wrap""`
}
func (a SomeStructA) MarshalJSON() ([]byte, error) {
return core.MarshalJson(a)
}
func (a *SomeStructA) UnmarshalJSON(b []byte) error {
*a = SomeStructA{}
err := core.UnmarshalJson(a, b)
if err != nil {
return err
}
return nil
}
// step3. serialize your struct SomeStructA to bytes, and deserialize bytes to SomeStructA
a1 := SomeStructA{
F1: &Bird{Name: "Flying Bird"},
F2: &Plane{Num: "Plane 01"},
}
b, err := json.Marshal(a1)
if err != nil {
t.Fatal(err)
}
t.Log(string(b))
a2 := SomeStructA{}
if err := json.Unmarshal(b, &a2); err != nil {
t.Fatal(err)
}
assert.Equal(t, a1, a2)
// {"F1":{"kind":"Bird","value":{"name":"Flying Bird"}},"F2":{"kind":"Plane","value":{"num":"Plane 01"}}}