2 回答
TA貢獻1865條經驗 獲得超7個贊
“對可能發生的事情有什么想法嗎?”
"XXBTZUSD"JSON數組中的元素本身就是數組,即"XXBTZUSD"是數組的數組。該OHLC類型是結構類型。stdlib 本身不會將 JSON 數組解組為 Go 結構。Go 結構可用于解組 JSON 對象。JSON 數組可以解組為 Go 切片或數組。
如果您只是打印來自 json.Unmarshal 的錯誤,您會清楚地看到這就是問題所在:
json:無法將數組解組到main.OHLC 類型的 Go 結構字段 Trades.result.XXBTZUSD
https://go.dev/play/p/D4tjXZVzDI_w
如果要將 JSON 數組解組為 Go 結構,則必須讓 Go 結構類型實現json.Unmarshaler接口。
func (o *OHLC) UnmarshalJSON(data []byte) error {
// first unmarshal the array into a slice of raw json
raw := []json.RawMessage{}
if err := json.Unmarshal(data, &raw); err != nil {
return err
}
// create a function that unmarshals each raw json element into a field
unmarshalFields := func(raw []json.RawMessage, fields ...interface{}) error {
if len(raw) != len(fields) {
return errors.New("bad number of elements in json array")
}
for i := range raw {
if err := json.Unmarshal([]byte(raw[i]), fields[i]); err != nil {
return err
}
}
return nil
}
// call the function
return unmarshalFields(
raw,
&o.Time,
&o.Open,
&o.High,
&o.Low,
&o.Close,
&o.Vwa,
&o.Volume,
&o.Count,
)
}
https://go.dev/play/p/fkFKLkaNaSU
TA貢獻1871條經驗 獲得超8個贊
您的代碼有一些問題:
從行尾刪除分號,這是多余的。
fmt.Errorf返回錯誤,而不是打印它,每次檢查你的錯誤并傳播它。我們可以在 golang 中將數字數組和字符串轉換為結構。
為了實現您想要的輸出,我們需要先轉換為中間容器,然后再轉換為我們想要的輸出:
package main
import (
"errors"
"fmt"
"log"
"net/http"
//"strings"
"encoding/json"
"io/ioutil"
)
type Resp struct {
Error []string `json:"error"`
Result Trades `json:"result"`
}
type IntermediateResp struct {
Error []string `json:"error"`
Result IntermediateTrades `json:"result"`
}
type IntermediateTrades struct {
Pair [][]interface{} `json:"XXBTZUSD"`
Last int `json:"last"`
}
type Trades struct {
Pair []OHLC `json:"result"`
Last int `json:"last"`
}
type OHLC struct {
TT float64
Open string
High string
Low string
Close string
Vwap string
Volume string
Count float64
}
/*func main() {
var data = [...]Trade{
Trade{5, "op", "hi", "lo", "cl", "vw", "vo", 2},
Trade{5, "op", "hi", "lo", "cl", "vw", "vo", 2},
}
}*/
func main() {
fmt.Println("in main")
err := getOhlc()
if err != nil {
log.Fatal(err)
}
}
func buildOHLC(l []interface{}) (*OHLC, error) {
if len(l) < 8 {
return nil, errors.New("short list")
}
return &OHLC{
TT: l[0].(float64),
Open: l[1].(string),
High: l[2].(string),
Low: l[3].(string),
Close: l[4].(string),
Vwap: l[5].(string),
Volume: l[6].(string),
Count: l[7].(float64),
}, nil
}
func convert(r IntermediateResp) (*Resp, error) {
result := &Resp{Error: r.Error, Result: Trades{Pair: make([]OHLC, len(r.Result.Pair)), Last: r.Result.Last}}
for i, v := range r.Result.Pair {
ohlc, err := buildOHLC(v)
if err != nil {
return nil, err
}
result.Result.Pair[i] = *ohlc
}
return result, nil
}
func getOhlc() error {
fmt.Println("in ohlc func")
resp, err := http.Get("https://api.kraken.com/0/public/OHLC?pair=XXBTZUSD")
if err != nil {
return fmt.Errorf("error after request, %v", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
if err != nil {
return fmt.Errorf("error when reading %v", err)
}
var jsonData IntermediateResp
err = json.Unmarshal(body, &jsonData)
if err != nil {
return fmt.Errorf("error when unmarshalling %v", err)
}
if len(jsonData.Error) > 0 {
return fmt.Errorf("error")
}
convertedOhlc, err := convert(jsonData)
if err != nil {
return fmt.Errorf("error when convertedOhlc %v", err)
}
fmt.Println(convertedOhlc)
return nil
}
我們定義 IntermediateResp 和 IntermediateTrades 用于 Unmarshaling json,然后將其轉換為實際的 Resp。
Trades我認為另一種方法是對結構使用自定義 Unmarshal 。
- 2 回答
- 0 關注
- 186 瀏覽
添加回答
舉報
