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 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计