Присвоить дополнительное поле при демаршаллинге объекта JSON в GO struct - PullRequest
0 голосов
/ 23 сентября 2018

Каков наилучший способ назначить дополнительное поле для структуры, и все это ссылается на подструктуру при кодировании его из байта [], и это поле не является частью байта unmarshalling []?

Позвольте мне уточнитьпо примеру ...

  1. У нас есть несколько структур:

    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"`
        ...
    }

Наша основная структура APIClient и имеет много методов для отправки или получения чего-либо (обертка API)

    type API struct {
        Token string
        PollInt int32
        URL string

        client *http.Client
    }

    func(a *API) ... () {

    }

    func(a *API) ... () {

    }

    ...

Основной цикл цикла делает запрос http и возвращает ответ json в виде «res» - [] байта, поэтому мы можем использовать json.Unmarshal для сопоставления его со специальной структурой обновления

    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
    }

Можно ли как-нибудь расширить ВСЕ структуры в цепочке немаркетинга для дополнительного поля при использовании json.Unmarshal

    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:"-"`
    }

Так что мы можем сделать что-то вроде:


    var result []Update
    err = json.Unmarshal(res.Result, &result, api)
    if err != nil {
        return nil, fmt.Errorf("getupdates: %s", err)
    }

А затем используйте его:


    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)
    }

Вся структура будет расширена API (встроенная структура) при немаршалинге ...

Мои мысли о решении:

  1. Патч стандартного кодирования / библиотека json - не лучший выбор
  2. Получить пользовательскую библиотеку кодирования и немного переписать - сомнительный выбор
  3. Вручную демонтировать весь объект - ужасный код

   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
    }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...