I'm testing out go json marshaling with embedded structs. However, I see that when I embed time.Time, why does it always override the other embedded structs even though they also provide their own custom marshaling? The code below always print out "0001-01-01T00:00:00Z"
package main
import (
"encoding/json"
"fmt"
"time"
)
type A struct {
}
func (a A) Print() {
fmt.Println("A")
}
type B struct {
B int
}
func (a A) MarshalJSON() ([]byte, error) {
return []byte(`"a"`), nil
}
func (b B) MarshalJSON() ([]byte, error) {
return []byte(`"b"`), nil
}
func (a B) Print() {
fmt.Println("A")
}
type C struct {
A
B
time.Time
C int `json:"C"`
}
func main() {
fmt.Println("Hello, 世界")
c := C{}
decode, err := json.Marshal(c)
if err != nil {
fmt.Println(err)
}
fmt.Println(string(decode))
}
If you embed multiple types that have identically named fields or methods, then those fields or methods will not be accessible directly anymore.
Selectors:
That means that, given the following set of types:
the expression
s3.F
is illegal:this is because there are more than one
F
at the shallowest depth. You can try it on playground.The same rules apply to methods. From this it follows that your type
C
does NOT satisfy thejson.Marshaler
interface because it embeds, at the same depth, more that one type that implements theMarshalJSON()
method. You can see that for yourself on playground.Then, however, the question still remains as to why the embedded
time.Time
's custom marshaling is used regardless. This is becausetime.Time
implements not only thejson.Marshaler
interface but also theencoding.TextMarshaler
interface (docs & playground). And thejson.Marshal
's documentation says the following:You can see here that the behaviour described above holds once you also have
A
orB
implement theencoding.TextMarshaler
interface, then thetime.Time
'sMarshalText
method will not be used anymore.