我有这段代码:
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响应才能正确完成,但我不能。 Unmarshaling继续出错(goroutine stack exceeds 1000000000-byte limit
)。我最好使用easyjson或ffjson进行此操作,但我们怀疑是否有可能。建议?
答案 0 :(得分:0)
您的UnmarshalJSON
函数以递归方式调用自身,这会导致堆栈的大小爆炸。
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
}
如果您有理由在json.Unmarshal
函数内调用UnmarshalJSON
,则必须使用其他类型。执行此操作的常用方法是使用本地别名:
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
实例。