如何将JSON数组解析为结构体(Struct)?

huangapple go评论70阅读模式
英文:

How to parse a JSON array into a Struct

问题

给定以下的REST调用...

https://api.bitfinex.com/v2/ticker/fUSD

...我得到以下的JSON数组作为结果:

[0.00073995,0.00067,30,10082128.5775703,0.000664,2,191337.1001453,-0.00003991,-0.057,0.00066009,94710166.80102274,0,0]

下面是我解析结果的方法:

const (
    URL = "https://api.bitfinex.com/v2/ticker/f"
)

type Tick struct {
    FlashReturnRate float64
    Bid             float64
    BidPeriod       int64
    BidSize         float64
    Ask             float64
    AskPeriod       int64
    AskSize         float64
    DailyChange     float64
    DailyChangePerc float64
    LastPrice       float64
    Volume          float64
    High            float64
    Low             float64
}

...

func (s *TickerService) Get(curry string) (*Tick, error) {
    req, err = http.NewRequest("GET", URL + curry, nil)
    if err != nil {
        return nil, err
    }

    resp, err := http.DefaultClient.Do(req); if err != nil {
        return nil, err
    }

    defer resp.Body.Close()

    var v []float64
    err = json.Unmarshal(resp.Body, &v)
    if err != nil {
        return nil, err
    }

    t := Tick{
        FlashReturnRate: v[0],
        Bid:             v[1],
        BidSize:         v[2],
        BidPeriod:       int64(v[3]),
        Ask:             v[4],
        AskSize:         v[5],
        AskPeriod:       int64(v[6]),
        DailyChange:     v[7],
        DailyChangePerc: v[8],
        LastPrice:       v[9],
        Volume:          v[10],
        High:            v[11],
        Low:             v[12],
    }

    return &t, nil
}

有没有更好的方法来构建Tick对象?

英文:

Given the following REST call...

https://api.bitfinex.com/v2/ticker/fUSD

... I get back the following result as a JSON array:

[0.00073995,0.00067,30,10082128.5775703,0.000664,2,191337.1001453,-0.00003991,-0.057,0.00066009,94710166.80102274,0,0]

Here below is how I parse the result:

const (
    URL = "https://api.bitfinex.com/v2/ticker/f"
)

type Tick struct {
    FlashReturnRate float64
    Bid             float64
    BidPeriod       int64
    BidSize         float64
    Ask             float64
    AskPeriod       int64
    AskSize         float64
    DailyChange     float64
    DailyChangePerc float64
    LastPrice       float64
    Volume          float64
    High            float64
    Low             float64
}

...

func (s *TickerService) Get(curry string) (*Tick, error) {
    req, err = http.NewRequest("GET", URL + curry, nil)
    if err != nil {
        return nil, err
    }

    resp, err := http.DefaultClient.Do(req); if err != nil {
        return nil, err
    }

    defer resp.Body.Close()

    var v []float64
    err = json.Unmarshal(resp.Body, &v)
    if err != nil {
        return nil, err
    }

    t := Tick{
        FlashReturnRate: v[0],
        Bid:             v[1],
        BidSize:         v[2],
        BidPeriod:       int64(v[3]),
        Ask:             v[4],
        AskSize:         v[5],
        AskPeriod:       int64(v[6]),
        DailyChange:     v[7],
        DailyChangePerc: v[8],
        LastPrice:       v[9],
        Volume:          v[10],
        High:            v[11],
        Low:             v[12],
    }

    return &t, nil
}

Is there a better way to build the Tick object?

答案1

得分: 1

你正在走在正确的道路上,但一个更可用的解决方案是创建一个自定义的解码器:

func (t *Tick) UnmarshalJSON(data []byte) error {
    var v []float64
    if err := json.Unmarshal(data, &v); err != nil {
        return err
    }
    t.FlashReturnRate = v[0]
    t.Bid = v[1]
    t.BidSize = int64(v[2]) // 这是一个整数吗?你的示例数据表明是,但你的代码表明不是。
    // ... 等等
    
    return nil
}

现在你可以直接将数据解码到你的 Tick 数据类型中:

var tick Tick
if err := json.Unmarshal(res.Body, &tick); err != nil {
    // 处理错误
}
英文:

You're on the right track, but a more usable solution would be to create a custom unmarshaler:

func (t *Tick) UnmarshalJSON(data []byte) error {
    var v []float64
    if err := json.Unmarshal(data, &v); err != nil {
        return err
    }
    t.FlashReturnRate = v[0]
    t.Bid = v[1]
    t.BidSize = int64(v[2]) // Is this an int? Your sample data suggests it is, your code suggests it isn't.
    // ... etc
    
    return nil
}

Now you can unmarshal directly to your Tick data type as:

var tick Tick
if err := json.Unmarshal(res.Body, &tick); err != nil {
    // Handle error
}

huangapple
  • 本文由 发表于 2017年9月13日 02:19:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/46183083.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定