JSON Unmarshal 不规则的 JSON 字段

huangapple go评论89阅读模式
英文:

JSON Unmarshal Irregular JSON field

问题

我有这段代码:

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
}

现在,我的JSON响应看起来像这样:

[{
	"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"
				]
			}
		}
	]
}]

最好的情况是,我会更改JSON响应以正确完成,但我不能这样做。解组继续出错(goroutine stack exceeds 1000000000-byte limit)。最好的情况是,我宁愿使用easyjsonffjson来完成,但我怀疑是否可能。有什么建议吗?

英文:

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

得分: 0

你的UnmarshalJSON函数在递归调用自身,这会导致堆栈大小爆炸。

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
}

如果你有理由在UnmarshalJSON函数内部调用json.Unmarshal,那么它必须是在不同的类型上进行。一种常见的方法是使用本地别名:

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

*t = Tags(*ta)

还要注意,在你的函数中,t = &Tags{}并没有起到任何作用;它给t赋了一个新值,但是该值在函数退出时就会丢失。如果你真的想给t赋值,你需要使用*t;但是除非你想取消之前设置的*Tags实例,否则你根本不需要这样做。

英文:

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.

huangapple
  • 本文由 发表于 2017年8月25日 04:22:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/45870273.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定