encoding/json: promoted Unmarshal method on embedded field caused confusionweb
接上一篇,官方在早上給了回覆:json
簡單解釋下就是嵌入字段 Nested
的方法被提高了,致使 Object
的方法不會被執行,因此 Num
字段不會被 Unmarshal
。跟上一篇中的解釋差很少意思。可是官方給了兩種更加優雅的解決這個問題的方式,讓咱們來欣賞下大佬的代碼。編輯器
代碼中只需添加下面一行便可:ide
var _ json.Unmarshaler = (*Object)(nil)
複製代碼
package main
import ( "encoding/json" "fmt" "time" ) var testJSON = `{"num":5,"duration":"5s"}` type Nested struct { Dur time.Duration `json:"duration"` } func (obj *Object) UnmarshalJSON(data []byte) error { tmp := struct { Dur string `json:"duration"` Num int `json:"num"` }{} if err := json.Unmarshal(data, &tmp); err != nil { return err } dur, err := time.ParseDuration(tmp.Dur) if err != nil { return err } obj.Dur = dur obj.Num = tmp.Num return nil } type Object struct { Nested Num int `json:"num"` } var _ json.Unmarshaler = (*Object)(nil) func main() { obj := Object{} _ = json.Unmarshal([]byte(testJSON), &obj) fmt.Printf("result: %+v \n", obj) } 複製代碼
隨後這位老哥補充到,在嵌入字段都實現了接口方法的狀況下,The type assertion will be a nice guide
, 添加該類型的斷言是一個好的實踐,能夠幫助你快速捕捉到潛在的 bug
。學習
實現 custom time unmarshaller
。ui
package main
import ( "encoding/json" "fmt" "time" ) var testJSON = `{"num":5,"duration":"5s"}` type customTimeDuration time.Duration type Nested struct { Dur customTimeDuration `json:"duration"` } func (ctd *customTimeDuration) UnmarshalJSON(b []byte) error { var durStr string if err := json.Unmarshal(b, &durStr); err != nil { return err } dur, err := time.ParseDuration(durStr) if err == nil { *ctd = customTimeDuration(dur) } return err } type Object struct { Nested Num int `json:"num"` } func main() { obj := Object{} _ = json.Unmarshal([]byte(testJSON), &obj) fmt.Printf("result: %+v \n", obj) } 複製代碼
這種方式其實就是跟以上一篇分開解析的思路比較像,他從新聲明瞭別名類型,而後爲這個別名類型實現 UnmarshalJson
接口。我的傾向於第一種添加類型斷言的方式,簡潔又容易理解 ,對代碼侵入比較小。url
官方對這個問題的回覆仍是很熱情的,他說他本身的團隊在幾年前也遇到了如出一轍的問題,很能理解開發者的心情,他當時還針對這個問題寫了一篇相似的文章,https://medium.com/@odeke_et/compile-type-assertions-to-the-rescue-6ddab4b8398b。我說啥來着,這是一個前人踩坑,後人踩坑,將來還會踩的坑。spa
u1s1, 這位大佬給出的方案和代碼仍是很賞心悅目的,值得學習(抄一下)。code
------------------------------ END ----------------------------------cdn