Як @chakrit згадував у коментарі, ви не можете змусити це працювати, реалізувавши json.Marshalerна MyStruct, а реалізація користувацької функції маршалінгу JSON на кожній структурі, що використовує її, може бути набагато більшою роботою. Це дійсно залежить від вашого варіанту використання, чи варто це зайвої роботи, чи готові ви жити з порожніми структурами у вашому JSON, але ось шаблон, який я використовую, застосовується до Result:
type Result struct {
Data MyStruct
Status string
Reason string
}
func (r Result) MarshalJSON() ([]byte, error) {
return json.Marshal(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
}{
Data: &r.Data,
Status: r.Status,
Reason: r.Reason,
})
}
func (r *Result) UnmarshalJSON(b []byte) error {
decoded := new(struct {
Data *MyStruct `json:"data,omitempty"`
Status string `json:"status,omitempty"`
Reason string `json:"reason,omitempty"`
})
err := json.Unmarshal(b, decoded)
if err == nil {
r.Data = decoded.Data
r.Status = decoded.Status
r.Reason = decoded.Reason
}
return err
}
Якщо у вас є величезні структури з багатьма полями, це може стати нудним, особливо змінивши реалізацію структури пізніше, але не переписавши весь jsonпакет відповідно до ваших потреб (не гарна ідея), це майже єдиний спосіб, я можу подумати про отримання це зроблено, зберігаючи там непоказник MyStruct.
Крім того, вам не потрібно використовувати вбудовані структури, ви можете створювати іменовані. Однак я використовую LiteIDE із заповненням коду, тому я волію вбудований, щоб уникнути безладу.