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?

douzao2590
douzao2590 len(b)==0将不起作用,因为实际为“””。
大约 3 年之前 回复
dougai6464
dougai6464 UnmarshalJSON通常不会收到空片。它至少类似于[],{},“”,0。通常,请勿转换为字符串来执行此操作;len(b)==0是可取的。
大约 3 年之前 回复
dongshuobei1037
dongshuobei1037 我喜欢JSON-to-Go,并在过去使用过它。我不是在寻找结构...而是在寻求将JSON正确编组到结构中的帮助。
大约 3 年之前 回复
doukao8851
doukao8851 查看JSON-to-Go。我粘贴了您的json,输出结果正确无误。它只是错过了风暴和关键字字段。
大约 3 年之前 回复

1个回答

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.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问