JSON 的填坑之旅:官方給的解答
encoding/json: promoted Unmarshal method on embedded field caused confusion
接上一篇:?golang 使用 UnmarshalJSON 接口實(shí)現(xiàn)自定義 unmarshal 的坑,官方給的回復(fù):

簡(jiǎn)單解釋下就是嵌入字段 Nested 的方法被提升了,導(dǎo)致 Object 的方法不會(huì)被執(zhí)行,所以 Num 字段不會(huì)被 Unmarshal。跟上一篇中的解釋差不多意思。但是官方給了兩種更加優(yōu)雅的解決這個(gè)問(wèn)題的方式,讓我們來(lái)欣賞下大佬的代碼。
方法 a
代碼中只需添加下面一行即可:
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)
}
隨后這位老哥補(bǔ)充到,在嵌入字段都實(shí)現(xiàn)了接口方法的情況下,The type assertion will be a nice guide, 添加該類型的斷言是一個(gè)好的實(shí)踐,可以幫助你快速捕捉到潛在的 bug。
方法 b
實(shí)現(xiàn) custom time unmarshaller。
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)
}
這種方式其實(shí)就是跟以上一篇分開(kāi)解析的思路比較像,他重新聲明了別名類型,然后為這個(gè)別名類型實(shí)現(xiàn) UnmarshalJson 接口。個(gè)人傾向于第一種添加類型斷言的方式,簡(jiǎn)潔又容易理解 ,對(duì)代碼侵入比較小。
官方對(duì)這個(gè)問(wèn)題的回復(fù)還是很熱情的,他說(shuō)他自己的團(tuán)隊(duì)在幾年前也遇到了一模一樣的問(wèn)題,很能理解開(kāi)發(fā)者的心情
,他當(dāng)時(shí)還針對(duì)這個(gè)問(wèn)題寫(xiě)了一篇類似的文章,https://medium.com/@odeke_et/compile-type-assertions-to-the-rescue-6ddab4b8398b。我說(shuō)啥來(lái)著,這是一個(gè)前人踩坑,后人踩坑,未來(lái)還會(huì)踩的坑。
u1s1, 這位大佬給出的方案和代碼還是很賞心悅目的,值得學(xué)習(xí)(抄一下)。
推薦閱讀
站長(zhǎng) polarisxu
自己的原創(chuàng)文章
不限于 Go 技術(shù)
職場(chǎng)和創(chuàng)業(yè)經(jīng)驗(yàn)
Go語(yǔ)言中文網(wǎng)
每天為你
分享 Go 知識(shí)
Go愛(ài)好者值得關(guān)注
