-2

我有一个来自 Kraken websocket 的 JSON,如下所示:

myJsonString := []byte(`[320,{"as":[["27346.80000","0.48700000","1609084588.716887"],["27350.00000","1.38867881","1609084599.606134"]],"bs":[["27346.70000","0.39439437","1609084613.201520"],["27342.10000","0.08750000","1609084611.036191"]]},"book-10","XBT/USD"]`)

我想解组到这样的结构:

type OrderBook struct {
    ChannelID   int
    A []OrderBookItem     `json:"as"`
    B []OrderBookItem     `json:"bs"`
    Depth       string
    Pair        string
}

type OrderBookItem struct {
    Price       float64
    Volume      float64
    Time        float64
}

我尝试将 unmarshal 放入一个切片中,但它没有给出所需的结果,因为它只是返回一个带有零的结构。我读了这个答案How to parse JSON arrays with two different data types into a struct in Golang,但那里的消息似乎不是一个数组。

func main() {

    myJsonString := []byte(`[320,{"as":[["27346.80000","0.48700000","1609084588.716887"],["27350.00000","1.38867881","1609084599.606134"]],"bs":[["27346.70000","0.39439437","1609084613.201520"],["27342.10000","0.08750000","1609084611.036191"]]},"book-10","XBT/USD"]`)

    var raw []OrderBook
    json.Unmarshal(myJsonString, &raw)
    fmt.Println(raw)
}

结果:

[{0 [] []  } {0 [{0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0}] [{0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0} {0 0 0}]  } {0 [] []  } {0 [] []  }]

我还尝试使用 interface{} 解组并使用 switch 来访问这些值,但这似乎很麻烦。

将其解组为结构的最佳做法是什么?

4

1 回答 1

0

您可以UnmarshalJSON为您的类型实现自定义方法。

func (ob *OrderBook) UnmarshalJSON(b []byte) error {
    var values []interface{}
    err := json.Unmarshal(b, &values)
    if err != nil {
        return err
    }

    if len(values) != 4 {
        return fmt.Errorf("unexpected number of order book values: %d", len(values))
    }

    ob.ChannelID = int(values[0].(float64))
    ob.Depth = values[2].(string)
    ob.Pair = values[3].(string)

    m := values[1].(map[string]interface{})

    ob.A, err = parseOrderBookItems(m["as"].([]interface{}))
    if err != nil {
        return err
    }

    ob.B, err = parseOrderBookItems(m["bs"].([]interface{}))
    return err
}

func parseOrderBookItems(items []interface{}) ([]OrderBookItem, error) {
    bookItems := make([]OrderBookItem, len(items))

    for i, item := range items {
        values := item.([]interface{})
        if len(values) != 3 {
            return nil, fmt.Errorf("unexpected number of order book item values: %d", len(values))
        }

        obi := OrderBookItem{}
        f, err := strconv.ParseFloat(values[0].(string), 64)
        if err != nil {
            return nil, err
        }
        obi.Price = f

        f, err = strconv.ParseFloat(values[1].(string), 64)
        if err != nil {
            return nil, err
        }
        obi.Volume = f

        f, err = strconv.ParseFloat(values[2].(string), 64)
        if err != nil {
            return nil, err
        }
        obi.Time = f

        bookItems[i] = obi
    }

    return bookItems, nil
}

这是操场上的一个例子:https: //play.golang.org/p/j7ydQCiqpcS

于 2021-01-03T16:53:53.127 回答