dpyu7978 2017-08-24 20:22
浏览 249
已采纳

JSON Unmarshal不规则JSON字段

I have this code:

type Response struct {
    ID string `json:"id"`
    Tags Tags `json:"tags,omitempty"`
}

type Tags struct {
    Geo     []string `json:"geo,omitempty"`
    Keyword []string `json:"keyword,omitempty"`
    Storm   []string `json:"storm,omitempty"`
}

func (t *Tags) UnmarshalJSON(b []byte) (err error) {
    str := string(b)
    if str == "" {
        t = &Tags{}
        return nil
    }

    err = json.Unmarshal(b, t)
    if err != nil {
        return err
    }

    return nil
}

Now, my JSON response looks like this:

[{
    "id": "/cms/v4/assets/en_US",
    "doc": [{
            "id": "af02b41d-c2c5-48ec-9dbc-ceed693bdbac",
            "tags": {
                "geo": [
                    "DMA:US.740:US"
                ]
            }
        },
        {
            "id": "6a90d9ed-7978-4c18-8e36-c01cf4260492",
            "tags": ""
        },
        {
            "id": "32cfd045-98ac-408c-b464-c74e02466339",
            "tags": {
                "storm": [
                    "HARVEY - AL092017"
                ],
                "keyword": [
                    "hurrcane",
                    "wunderground"
                ]
            }
        }
    ]
}]

Preferably, I'd change the JSON response to be done correctly, but I cannot. Unmarshaling continues to error out (goroutine stack exceeds 1000000000-byte limit). Preferably, I'd rather do this using easyjson or ffjson but doubt it is possible. Suggestions?

  • 写回答

1条回答 默认 最新

  • dprq18175 2017-08-24 20:51
    关注

    Your UnmarshalJSON function calls itself recursively, which will cause the stack to explode in size.

    func (t *Tags) UnmarshalJSON(b []byte) (err error) {
        str := string(b)
        if str == "" {
            t = &Tags{}
            return nil
        }
    
        err = json.Unmarshal(b, t) <--- here it calls itself again
        if err != nil {
            return err
        }
    
        return nil
    }
    

    If you have a reason to call json.Unmarshal from within a UnmarshalJSON function, it must be on a different type. A common way to do this is to use a local alias:

        type tagsAlias Tags
        var ta = &tagsAlias
        err = json.Unmarshal(b, ta)
        if err != nil {
            return err
        }
    
        *t = Tags(ta)
    

    Also note that t = &Tags{} does nothing in your function; it assigns a new value to t, but that value is lost as soon as the function exits. If you really want to assign to t, you need *t; but you also don't need that at all, unless you're trying to unsset a previously set instance of *Tags.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊
  • ¥15 安装svn网络有问题怎么办