arrays - 将 JSON 数组 API 响应转换为结构
问题描述
使用 Go,我希望查询 API 端点并将结果输出到 Gorm SQLite DB。这已经在(此处)之前完成,但我需要自己编写代码。
API 端点返回一个 JSON 数组,对于数组中的每笔交易,我想将其放入一个结构中,然后将其作为行添加到 SQLite 数据库中。
结构定义如下:
type Trade struct {
TradeID int64 `json:"id"`
Price string `json:"price"`
Qty string `json:"qty"`
QuoteQty string `json:"quoteQty"`
Time int64 `json:"time"`
IsBuyerMaker bool `json:"isBuyerMaker"`
IsBestMatch bool `json:"isBestMatch"`
}
这些类型可能看起来很奇怪,但通过使用 PowerShell 和以下代码确定:
PS C:\Git> $body = @{"symbol" = "ETHEUR";"limit" = 1000}
PS C:\Git> $response = Invoke-RestMethod https://api.binance.com/api/v3/trades -Body $body
PS C:\Git> $response[0] | gm
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
id NoteProperty long id=21731777
isBestMatch NoteProperty bool isBestMatch=True
isBuyerMaker NoteProperty bool isBuyerMaker=True
price NoteProperty string price=3539.03000000
qty NoteProperty string qty=0.28600000
quoteQty NoteProperty string quoteQty=1012.16258000
time NoteProperty long time=1620822731248
所以,我到目前为止的Go函数如下:
func getTrade(symbol string, limit int) {
uri := fmt.Sprintf("https://api.binance.com/api/v3/trades?symbol=%v&limit=%v", symbol, limit)
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
// Create the fields in the database based on the Trade Struct
db.AutoMigrate(&Trade{})
// Query Binance API endpoint
response, err := http.Get(uri)
// Log if an error occurred
if err != nil {
log.Fatalln(err)
}
// Defer closing object
defer response.Body.Close()
// Create trade struct
trade := Trade{}
从这里我尝试了几种将响应转换为结构的各种方法,但失败了。这些方法包括:
// Unmarshal bytes to data struct
_ = json.Unmarshal([]byte(responseData), &trade)
var myClient = &http.Client{Timeout: 10 * time.Second}
func getJson(url string, target interface{}) error {
response, err := myClient.Get(url)
if err != nil {
return err
}
defer response.Body.Close()
return json.NewDecoder(response.Body).Decode(target)
}
// Iterate through trades returned (this doesn't work)
for _, trade := range responseData {
tradeVariable := Trade{}
tradeVariable.TradeID = trade.id
fmt.Println(tradeVariable.TradeID)
}
我感觉真的被困住了,就像我错过了与编组有关的东西,有人可以帮我吗?
解决方案
由于 JSON 响应是一个数组,因此您需要将其解组为一个结构切片。确保您还使用了正确的 Go 类型。用于float64
JSON 数字。
type Trade struct {
TradeID float64 `json:"id"`
Price string `json:"price"`
Qty string `json:"qty"`
QuoteQty string `json:"quoteQty"`
Time float64 `json:"time"`
IsBuyerMaker bool `json:"isBuyerMaker"`
IsBestMatch bool `json:"isBestMatch"`
}
func main() {
symbol := "ETHEUR"
limit := 1000
uri := fmt.Sprintf("https://api.binance.com/api/v3/trades?symbol=%v&limit=%v", symbol, limit)
response, err := http.Get(uri)
if err != nil {
fmt.Println(err)
}
body, err := ioutil.ReadAll(response.Body)
if err != nil {
fmt.Println(err)
}
defer response.Body.Close()
trade := []Trade{}
err = json.Unmarshal([]byte(body), &trade)
if err != nil {
fmt.Println(err)
}
fmt.Println(trade)
}
推荐阅读
- java - 使用给定的 JUNIT 测试在数组中找到最接近平均值的值
- timer - 在触发回调nodemcu之前删除计时器警报
- php - 让我们在 LEMP Ubuntu 16.04 上使用 Nginx 加密 Laravel 应用程序
- java - Java Futures 在使用 Mockito 时返回 null
- c++ - 模板模板参数中模板参数数量不匹配
- python - Zeppelin & spark.ipyspark & folium
- python - 按下按钮时退出while循环
- python - Tkinter 窗口未从线程打开,使用来自套接字连接的数据
- javascript - react-input-range 不会在 react-leaflet Map 中触发事件(onChange,onClick)
- rotational-matrices - 旋转局部点时结果错误