使用自訂 MarshalJSON() 嵌入結構的慣用方法
當嵌入結構定義自訂 MarshalJSON() 方法時,就會出現挑戰,導致意外的 JSON序列化行為當試圖編組包含struct.
背景
考慮以下結構定義:
1 2 3 4 5 6 7 8 | type Person struct {
Name string `json: "name" `
}
type Employee struct {
*Person
JobRole string `json: "jobRole" `
}
|
登入後複製
如預期編組Employee 結構很簡單:
1 2 3 4 | p := Person{ "Bob" }
e := Employee{&p, "Sales" }
output, _ := json.Marshal(e)
fmt.Printf( "%s\n" , string(output))
|
登入後複製
輸出:
1 | { "name" : "Bob" , "jobRole" : "Sales" }
|
登入後複製
問題
但是,為嵌入結構定義自訂MarshalJSON() 方法(如下所示)會破壞預期的序列化:
1 2 3 4 5 6 7 | func (p *Person) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
Name string `json: "name" `
}{
Name: strings.ToUpper(p.Name),
})
}
|
登入後複製
現在,編組Employee 會產生帶有name 欄位的輸出轉換為大寫但缺少jobRole欄位:
慣用語解決方案
為了維持所需的序列化行為,請避免在嵌入結構 (Person) 上定義 MarshalJSON() 方法。相反,建立封裝自訂編組邏輯的單獨類型並嵌入該類型:
1 2 3 4 5 6 7 8 9 10 11 12 13 | type Name string
func (n Name) MarshalJSON() ([]byte, error) {
return json.Marshal(struct{
Name string `json: "name" `
}{
Name: strings.ToUpper(string(n)),
})
}
type Person struct {
Name Name `json: "name" `
}
|
登入後複製
此方法將編組自訂隔離為專用類型,防止在其他地方嵌入 Person 結構時出現意外的副作用。
範例:https://play.golang.org/p/u96T4C6PaY
以上是如何在 Go 中慣用地嵌入自訂 `MarshalJSON()` 的結構?的詳細內容。更多資訊請關注PHP中文網其他相關文章!