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?

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.