Como @chakrit mencionado em um comentário, você não pode chegar a este trabalho através da implementação json.Marshaler
de MyStruct
, e implementar uma função de triagem JSON personalizado em cada struct que usa-lo pode ser muito mais trabalho. Realmente depende do seu caso de uso se vale a pena o trabalho extra ou se você está preparado para viver com estruturas vazias em seu JSON, mas aqui está o padrão que uso aplicado a 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
}
Se você tem structs enormes com muitos campos, isso pode se tornar tedioso, especialmente alterar a implementação de um struct mais tarde, mas sem reescrever todo o json
pacote para atender às suas necessidades (não é uma boa ideia), essa é praticamente a única maneira que consigo pensar em conseguir isso é feito enquanto mantém um não-ponteiro MyStruct
lá.
Além disso, você não precisa usar estruturas embutidas, você pode criar estruturas nomeadas. Eu uso LiteIDE com autocompletar de código, então eu prefiro inline para evitar confusão.