Le *_*ong 2 go encoding-json-go
我正在测试带有嵌入式结构的 go json 封送处理。但是,我发现当我嵌入 time.Time 时,为什么它总是覆盖其他嵌入的结构,即使它们也提供自己的自定义封送处理?下面的代码总是打印出来"0001-01-01T00:00:00Z"
package main\n\nimport (\n "encoding/json"\n "fmt"\n "time"\n)\n\ntype A struct {\n}\n\nfunc (a A) Print() {\n fmt.Println("A")\n}\n\ntype B struct {\n B int\n}\n\nfunc (a A) MarshalJSON() ([]byte, error) {\n return []byte(`"a"`), nil\n}\n\nfunc (b B) MarshalJSON() ([]byte, error) {\n return []byte(`"b"`), nil\n}\n\nfunc (a B) Print() {\n fmt.Println("A")\n}\n\ntype C struct {\n A\n B\n time.Time\n C int `json:"C"`\n}\n\nfunc main() {\n fmt.Println("Hello, \xe4\xb8\x96\xe7\x95\x8c")\n c := C{}\n decode, err := json.Marshal(c)\n if err != nil {\n fmt.Println(err)\n }\n fmt.Println(string(decode))\n}\n\nRun Code Online (Sandbox Code Playgroud)\n
如果您嵌入具有相同名称字段或方法的多个类型,则将无法再直接访问这些字段或方法。
选择器:
x.f
x对于typeT或*TwhereT不是指针或接口类型的值,表示存在此类 的x.f最浅深度的字段或方法。如果不存在深度最浅的选择器表达式 ,则该选择器表达式是非法的。Tff
这意味着,给定以下一组类型:
type S1 struct { F string }
type S2 struct { F string }
type S3 struct {
S1
S2
}
Run Code Online (Sandbox Code Playgroud)
该表达式s3.F是非法的:
var s3 S3
_ = s3.F // ambiguous selector s3.F
Run Code Online (Sandbox Code Playgroud)
这是因为在最浅的深度有不止一个F。你可以在操场上尝试一下。
相同的规则适用于方法。由此可见,您的类型C不满足json.Marshaler接口,因为它在相同的深度嵌入了不止一种实现该MarshalJSON()方法的类型。您可以在操场上亲自看到这一点。
然而,问题仍然是为什么time.Time无论如何都要使用嵌入式的自定义封送处理。这是因为time.Time不仅实现了json.Marshaler接口,还encoding.TextMarshaler实现了接口(文档和游乐场)。的json.Marshal文档说明如下:
Marshal 递归地遍历值 v。如果遇到的值实现了
Marshaler接口并且不是 nil 指针,Marshal 会调用其MarshalJSON方法来生成 JSON。如果不MarshalJSON存在任何方法,但值实现encoding.TextMarshaler了,Marshal 会调用其MarshalText方法并将结果编码为 JSON 字符串。
您可以在这里看到A,一旦您也拥有或B实现了该接口,上述行为就成立encoding.TextMarshaler,那么time.Time'sMarshalText方法将不再被使用。