What is the best way to assign additional field to struct and all it references sub-structure when encoding it from []byte and this field is not a part of unmarshalling []byte?
Let me clarify by example...
type Update struct { UpdateID int32 `json:"update_id"` Message *Message `json:"message,omitempty"` ... } type Message struct { MessageID int32 `json:"message_id"` From *User `json:"from,omitempty"` Date int32 `json:"date"` Chat Chat `json:"chat"` ... }
type API struct { Token string PollInt int32 URL string client *http.Client } func(a *API) ... () { } func(a *API) ... () { } ...
func (a *API) GetUpdates(ctx context.Context, gu *GetUpdates) ([]Update, error) { buf := bytes.Buffer{} err := json.NewEncoder(&buf).Encode(gu) if err != nil { return nil, fmt.Errorf("getupdates: %s", err) } res, err := a.DoRequest(&ctx, "getUpdates", &buf) if err != nil { return nil, fmt.Errorf("getupdates: %s", err) } var result []Update err = json.Unmarshal(res.Result, &result) if err != nil { return nil, fmt.Errorf("getupdates: %s", err) } return result, nil }
type Update struct { UpdateID int32 `json:"update_id"` Message *Message `json:"message,omitempty"` ... API `json:"-"` } type Message struct { MessageID int32 `json:"message_id"` From *User `json:"from,omitempty"` Date int32 `json:"date"` Chat Chat `json:"chat"` ... API `json:"-"` }
So we can do something like:
var result []Update err = json.Unmarshal(res.Result, &result, api) if err != nil { return nil, fmt.Errorf("getupdates: %s", err) }
And then use it:
result[0].RejectUpdate() result[0].Message.SendReply() ... func (u *Update) RejectUpdate(cause string) { m.API.SendMessage(u.Chat.ID, text) m.API.Reject(u.ID, cause) } func (m *Message) SendReply(text string) { m.API.SendMessage(m.Chat.ID, text) }
All struct will be extended by api (embedded struct) on unmarshaling...
My thoughts about solution:
type Bot struct { superCLient string } type Image struct { Name string Path string *Bot `json:"-"` } type FormFile struct { Img *Image Name string *Bot `json:"-"` } func main() { data := []byte(`{"Img": {"Name": "Vi", "Path": "/etc/log"}, "Name": "Josh"}`) bot := &Bot{ superCLient: "ClientExample", } var omg FormFile omg.CustomUnmarshal(data, bot) fmt.Println(omg) } func (ff *FormFile) CustomUnmarshal(data []byte, bot *Bot) error { var f map[string]*json.RawMessage json.Unmarshal(data, &f) var i Image i.CustomUnmarshal(*f["Img"], bot) ff.Img = &i json.Unmarshal(*f["Name"], ff.Name) ff.Bot = bot return nil } func (img *Image) CustomUnmarshal(data []byte, bot *Bot) error { err := json.Unmarshal(data, img) img.Bot = bot return err }