Reputation: 2815
I have a struct that I would like to efficiently JSON encode:
type MyStruct struct {
*Meta
Contents []interface{}
}
type Meta struct {
Id int
}
The struct contains meta data of a known form and Contents of an unknown form, The contents list is populated during runtime, so I don't really have control over them. To improve Go's marshalling speed, I would like to implement the Marshaller interface over the Meta struct. The Marshaller interface looks like this:
type Marshaler interface {
MarshalJSON() ([]byte, error)
}
Please keep in mind that the Meta struct is not as simple as shown here. I've tried implementing the Marshaler interface over the Meta struct, but it seems that when I then JSON marshal MyStruct, the result is only the result returned by the Meta marshalling interface.
So my question is: How can I JSON marshal a struct, that contains en embedded struct with its own JSON marshaller and another struct without one?
Upvotes: 5
Views: 4380
Reputation: 77925
Since the MarshalJSON
method of the anonymous field *Meta
will be promoted to MyStruct
, the encoding/json
package will use that method when MyStruct will be marshalled.
What you can do is, instead of letting Meta
implement the Marshaller
interface, you can implement the interface on MyStruct like this:
package main
import (
"fmt"
"encoding/json"
"strconv"
)
type MyStruct struct {
*Meta
Contents []interface{}
}
type Meta struct {
Id int
}
func (m *MyStruct) MarshalJSON() ([]byte, error) {
// Here you do the marshalling of Meta
meta := `"Id":` + strconv.Itoa(m.Meta.Id)
// Manually calling Marshal for Contents
cont, err := json.Marshal(m.Contents)
if err != nil {
return nil, err
}
// Stitching it all together
return []byte(`{` + meta + `,"Contents":` + string(cont) + `}`), nil
}
func main() {
str := &MyStruct{&Meta{Id:42}, []interface{}{"MyForm", 12}}
o, err := json.Marshal(str)
if err != nil {
panic(err)
}
fmt.Println(string(o))
}
{"Id":42,"Contents":["MyForm",12]}
Upvotes: 4