亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

在 golang 中解組 JSON

在 golang 中解組 JSON

Go
開心每一天1111 2022-11-23 15:27:25
我在讓我的程序運行時遇到了很多麻煩。我想解組一些非常簡單的東西,但不幸的是,它給了我很多問題。這是我要解組的響應:{"error":[],"result":{"XXBTZUSD":[[1647365820,"39192.0","39192.0","39191.9","39191.9","39191.9","0.18008008",10],[1647365880,"39186.1","39186.1","39172.0","39176.0","39174.4","0.13120077",10]],"last":1647408900}}我寫了這些結構來幫助解組type Resp struct {    Error   []string        `json:"error"`    Result  Trades          `json:"result"`}type Trades struct {    Pair    []OHLC          `json:"XXBTZUSD"`    Last    float64         `json:"last"`}type OHLC struct {    Time    float64    Open    string    High    string    Low     string    Close   string    Vwa     string    Volume  string    Count   float64}我有一個函數調用,它發出 http 請求,然后解組數據。無論出于何種原因,當 Pair 類型為 []OHLC 或 []*OHLC 時,我的代碼甚至會在啟動 http 請求函數調用和后續解組之前結束。如果我將 Pair 類型更改為 interface{},它就會運行。不過,我想讓它與 OHLC 結構一起使用。
查看完整描述

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


查看完整回答
反對 回復 2022-11-23
?
ITMISS

TA貢獻1871條經驗 獲得超8個贊

您的代碼有一些問題:

  1. 從行尾刪除分號,這是多余的。

  2. fmt.Errorf返回錯誤,而不是打印它,每次檢查你的錯誤并傳播它。

  3. 我們可以在 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 。


查看完整回答
反對 回復 2022-11-23
  • 2 回答
  • 0 關注
  • 186 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號