调用AlphaVantage API后JSON解码得到空结构体的问题排查
解决AlphaVantage Income Statement接口反序列化空值问题
问题重现
调用AlphaVantage的INCOME_STATEMENT接口,将响应反序列化为自定义IncomeStmt结构体时,无错误抛出,但结果始终为&{ [] []},所有字段均未正确赋值。已确认结构体字段名称、类型与API响应一致,且字段已正确导出,getJson函数可处理简单API响应。
核心问题
问题出在getJson函数的反序列化逻辑上:
func getJson(resp *http.Response, data interface{}) error { defer resp.Body.Close() return json.NewDecoder(resp.Body).Decode(&data) }
当调用getJson(resp, incomeStmt)时,incomeStmt是*IncomeStmt类型的指针。此时&data会将其转为**IncomeStmt(指向指针的指针),JSON解码器会将数据解码到这个新的指针地址中,而非原incomeStmt指向的结构体。原结构体因此未被赋值,保持初始空状态。
修复方案
修改getJson函数,直接将data传入Decode(data本身已是可接受的指针类型,json.Decoder会自动处理interface{}中的指针):
func getJson(resp *http.Response, data interface{}) error { defer resp.Body.Close() return json.NewDecoder(resp.Body).Decode(data) }
移除Decode参数前的&符号,让解码器直接操作传入的指针指向的内存空间。
额外验证步骤
- 确认API响应的顶层字段与
IncomeStmt结构体的json标签完全匹配:symbol对应json:"symbol"annualReports对应json:"annualReports"quarterlyReports对应json:"quarterlyReports"
- 可临时在反序列化前打印响应内容,确认API返回数据正常:
func (c *client) GetIncomeStmt(symbol string) (*IncomeStmt, error) { // ... 现有代码 ... resp, err := c.get(u) if err != nil { return nil, err } // 临时打印响应内容,验证数据 body, _ := io.ReadAll(resp.Body) fmt.Println("API Response:", string(body)) // 重新读取Body,因为ReadAll后Body已被消耗 resp.Body = io.NopCloser(bytes.NewBuffer(body)) incomeStmt := &IncomeStmt{} if err = getJson(resp, incomeStmt); err != nil { fmt.Print(err) log.Fatal("Error decoding data in getJson fn.") return nil, err } // ... 现有代码 ... }
修复后重新运行,fmt.Printf("Unmarshaled IncomeStmt: %v \n", incomeStmt)即可打印出完整的API响应内容。
内容的提问来源于stack exchange,提问作者Zac
相关产品推荐
相关产品推荐

