首页 > 解决方案 > 将 JSON 对象解组到结构时分配附加字段

问题描述

从 []byte 编码时,将附加字段分配给结构及其所有引用子结构的最佳方法是什么,并且该字段不是解组 []byte 的一部分?

让我通过例子来澄清......

  1. 我们有几个结构:
    类型更新结构{
        UpdateID int32 `json:"update_id"`
        消息 *消息 `json:"message,omitempty"`
        ...
    }

    类型消息结构{
        MessageID int32 `json:"message_id"`
        来自 *用户 `json:"from,omitempty"`
        日期 int32 `json:"date"`
        聊天聊天`json:"chat"`
        ...
    }

  1. 我们的核心结构是 APIClient,它有许多发送或获取东西的方法(API 包装器)
    类型 API 结构 {
        令牌字符串
        PollInt int32
        网址字符串

        客户端 *http.Client
    }

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

    }

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

    }

    ...

  1. 主循环轮询器发出 http 请求并将 json 响应返回为“res” - []byte,因此我们可以使用 json.Unmarshal 将其映射到特殊的 Update struct
    func (a *API) GetUpdates(ctx context.Context, gu *GetUpdates) ([]Update, error) {
        buf := bytes.Buffer{}
        错误:= json.NewEncoder(&buf).Encode(gu)
        如果错误!= nil {
            返回 nil, fmt.Errorf("getupdates: %s", err)
        }

        res, err := a.DoRequest(&ctx, "getUpdates", &buf)
        如果错误!= nil {
            返回 nil, fmt.Errorf("getupdates: %s", err)
        }

        var 结果 [] 更新
        错误 = json.Unmarshal(res.Result, &result)
        如果错误!= nil {
            返回 nil, fmt.Errorf("getupdates: %s", err)
        }

        返回结果,无
    }

  1. 使用 json.Unmarshal 时,是否可以通过任何方式扩展解组链中的所有结构以获得附加字段
    类型更新结构{
        UpdateID int32 `json:"update_id"`
        消息 *消息 `json:"message,omitempty"`
        ...

        API `json:"-"`
    }

    类型消息结构{
        MessageID int32 `json:"message_id"`
        来自 *用户 `json:"from,omitempty"`
        日期 int32 `json:"date"`
        聊天聊天`json:"chat"`
        ...

        API `json:"-"`
    }

所以我们可以这样做:

    var 结果 [] 更新
    错误 = json.Unmarshal(res.Result, &result, api)
    如果错误!= nil {
        返回 nil, fmt.Errorf("getupdates: %s", err)
    }

然后使用它:

    结果[0].RejectUpdate()
    结果[0].Message.SendReply()
    ...
    func (u *Update) RejectUpdate(原因字符串) {
      m.API.SendMessage(u.Chat.ID,文本)
      m.API.Reject(u.ID, 原因)
    }
    func (m *Message) SendReply(文本字符串) {
      m.API.SendMessage(m.Chat.ID,文本)
    }

所有结构都将在解组时由 api(嵌入式结构)扩展......

我对解决方案的想法:

  1. 补丁标准编码/json库——不是一个好的选择
  2. 获取自定义编码库并稍微重写 - 值得怀疑的选择
  3. 手动解组所有对象——糟糕的代码
   键入机器人结构 {
        超级客户端字符串
    }

    输入图像结构 {
        名称字符串
        路径字符串

        *机器人`json:"-"`
    }

    类型 FormFile 结构 {
        图片 *图片
        名称字符串

        *机器人`json:"-"`
    }

    功能主要(){
        data := []byte(`{"Img": {"Name": "Vi", "Path": "/etc/log"}, "Name": "Josh"}`)
        机器人 := &Bot{
            superCLient: "ClientExample",
        }
        var omg FormFile
        omg.CustomUnmarshal(数据,机器人)
        fmt.Println(omg)
    }

    func (ff *FormFile) CustomUnmarshal(data []byte, bot *Bot) 错误 {
        var f map[string]*json.RawMessage
        json.Unmarshal(数据,&f)

        变量 i 图像
        i.CustomUnmarshal(*f["Img"], bot)
        ff.Img = &i

        json.Unmarshal(*f["Name"], ff.Name)

        ff.Bot = 机器人

        返回零
    }

    func (img *Image) CustomUnmarshal(data []byte, bot *Bot) 错误 {
        错误:= json.Unmarshal(数据,img)
        img.Bot = 机器人
        返回错误
    }

标签: jsongostruct

解决方案


推荐阅读