Closed pyroxymat closed 5 years ago
what you can do is:
type Header struct {
Id string
}
type EchoMessage struct {
Contents string
}
type jsonHeader struct {
Header
EchoMessage
}
And they will be encoded as, and can be decoded from:
{"Id": "my_id", "Contents": "my_contents"}
We take advantage of go's support for embedded/anonymous types here.
But you will need to work within this constraint to design your usecase.
See https://godoc.org/github.com/ugorji/go/codec#Encoder.Encode (and search for anonymous)
P.S. interfaces cannot be inlined, because we cannot know the structure until runtime, and the structure may change at runtime. This is specified in the docs.
@wheldring ^^
Please respond here if/as necessary.
Thanks for your help @ugorji. The main reason I cannot use the first solution is because there might be 40 messages, so that means I need to write 40 different headers.
In the end I solved my problem by writing a custom encoder like this:
func (h jsonHeader) CodecEncodeSelf(enc *codec.Encoder) {
out := make(map[string]interface{})
out["msg_type"] = h.Header.MsgType
val := reflect.Indirect(reflect.ValueOf(h.Message))
typ := val.Type()
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
name := typ.Field(i).Name
out[field.Tag.Get("codec")] = val.FieldByName(name).Interface()
}
enc.MustEncode(out)
}
With the decoder as said in the main message. Although it is not beautiful it works. I guess I can clean it up by writing a custom decoder to be even more idiomatic.
I was wondering if it is possible to inline interfaces/structs like this:
Such that header and the message contents are on the same level.
Thus if the header and message struct were defined as follows:
I would expect the following output after encoding it with json:
EDIT: After some more thought I guess the issue is mainly in the decoding part since you don't know what the type of the message is when you decode it.
In my code so far I fixed this by running decode twice: 1 time to get the header (which contains the type) and then switching on the type and decoding the same JSON again for the message. I do not have a good solution on how to solve this while allowing inline encoding.