2 回答

TA貢獻1841條經(jīng)驗 獲得超3個贊
另一個答案的替代方法是聲明一個命名map[string]AddressIf類型并讓它實現(xiàn)json.Unmarshaler接口,然后你不必做任何臨時/匿名類型和轉(zhuǎn)換舞蹈。
type AddressMap map[string]AddressIf
func (m *AddressMap) UnmarshalJSON(b []byte) error {
if *m == nil {
*m = make(AddressMap)
}
raw := make(map[string]json.RawMessage)
if err := json.Unmarshal(b, &raw); err != nil {
return err
}
for key, val := range raw {
switch key {
case "home":
dst := new(AddressHome)
if err := json.Unmarshal(val, dst); err != nil {
return err
}
(*m)[key] = dst
case "work":
dst := new(AddressWork)
if err := json.Unmarshal(val, dst); err != nil {
return err
}
(*m)[key] = dst
}
}
return nil
}
https://play.golang.org/p/o7zV8zu9g5X

TA貢獻1821條經(jīng)驗 獲得超5個贊
為避免復(fù)制聯(lián)系人字段,請使用對象嵌入來隱藏需要特殊處理的字段。
使用工廠模式來消除跨地址類型的代碼重復(fù)。
有關(guān)更多信息,請參閱評論:
var addressFactories = map[string]func() AddressIf{
"home": func() AddressIf { return &AddressHome{} },
"work": func() AddressIf { return &AddressWork{} },
}
func (self *Contact) UnmarshalJSON(b []byte) error {
// Declare type with same base type as Contact. This
// avoids recursion below because this type does not
// have Contact's UnmarshalJSON method.
type contactNoMethods Contact
// Unmarshal to this value. The Contact.AddressMap
// field is shadowed so we can handle unmarshal of
// each value in the map.
var data = struct {
*contactNoMethods
AddressMap map[string]json.RawMessage `json:"address_map"`
}{
// Note that all fields except AddressMap are unmarshaled
// directly to Contact.
(*contactNoMethods)(self),
nil,
}
if err := json.Unmarshal(b, &data); err != nil {
return err
}
// Unmarshal each addresss...
self.AddressMap = make(map[string]AddressIf, len(data.AddressMap))
for k, raw := range data.AddressMap {
factory := addressFactories[k]
if factory == nil {
return fmt.Errorf("unknown key %s", k)
}
address := factory()
if err := json.Unmarshal(raw, address); err != nil {
return err
}
self.AddressMap[k] = address
}
return nil
}
在對該問題的評論中,OP 表示不應(yīng)使用其他類型。這個答案使用了兩種額外contactNoMethods的類型(和匿名類型data)。
- 2 回答
- 0 關(guān)注
- 136 瀏覽
添加回答
舉報