解封没有密钥的嵌套json [英] Unmarshal a nested json without a key
问题描述
我不是不能从Kraken
API接收的Golang结构中强制转换以下json
:
I am not unable to cast the following json
in a struct in Golang, received from Kraken
API:
{
"error": [],
"result": {
"LINKUSD": {
"asks": [
["2.049720", "183.556", 1576323009],
["2.049750", "555.125", 1576323009],
["2.049760", "393.580", 1576323008],
["2.049980", "206.514", 1576322995]
],
"bids": [
["2.043800", "20.691", 1576322350],
["2.039080", "755.396", 1576323007],
["2.036960", "214.621", 1576323006],
["2.036930", "700.792", 1576322987]
]
}
}
}
他使用json-to-go
为我提供了以下结构:
Using json-to-go
, he gives me the following struct:
type AutoGenerated struct {
Error []interface{} `json:"error"`
Result struct {
LINKUSD struct {
Asks [][]interface{} `json:"asks"`
Bids [][]interface{} `json:"bids"`
} `json:"LINKUSD"`
} `json:"result"`
}
很显然,我不能对LINKUSD
进行硬编码,因为对于每种货币对它都会改变.
Obviously, i can't hardocode the LINKUSD
cause it will change for every currency pairs.
我已经创建了两个结构来完成任务,但是我无法将结果强制转换为struct.
I've created two structure for accomplish the task, but i'm not able to cast the result in the struct.
type BitfinexOrderBook struct {
Pair string `json:"pair"`
Asks []BitfinexOrder `json:"asks"`
Bids []BitfinexOrder `json:"bids"`
}
type BitfinexOrder struct {
Price string
Volume string
Timestamp time.Time
}
我的第一个尝试是使用反射.阅读上面发布的JSON数据,我能够检索包含asks
和bids
列表的接口.
My first attempt was to use reflection. Reading the JSON data posted above, i'm able to retrieve an interface that contains the asks
and bids
list.
// Just used as a divisor
const div string = " ---------------------------------"
func test(data []byte) error {
var err error
// Creating the maps for the JSON data
m := map[string]interface{}{}
// Parsing/Unmarshalling the json readed from the file
err = json.Unmarshal(data, &m)
if err != nil {
log.Println("Error unmarshalling data: " + err.Error())
return err
}
// Extract the "result" only
a := reflect.ValueOf(m["result"])
if a.Kind() == reflect.Map {
key := a.MapKeys()[0] // Extract the key -> LINKUSD
log.Println("KEY: ", key, div)
strct := a.MapIndex(key) // Extract the value -> asks and bids array
log.Println("MAP: ", strct, div)
m, _ := strct.Interface().(map[string]interface{})
log.Println("Asks: ", m["asks"], div) // This will print [[value, value, value] ...] related to asks
log.Println("Bids: ", m["bids"], div) // This will print [[value, value, value] ...] related to bids
// Parse the interface into a []byte
asks_data, err := json.Marshal(m["asks"])
log.Println("OK: ", err, div)
log.Println("ASKS: ", string(asks_data), div)
// Tried without array to (datastructure.BitfinexOrder)
var asks []datastructure.BitfinexOrder
err = json.Unmarshal(asks_data, &asks)
log.Println("ERROR: ", err, div)
log.Println("UNMARSHAL: ", asks, div)
}
return errors.New("UNABLE_PARSE_VALUE")
}
m, _ := strct.Interface().(map[string]interface{})
下方的两个打印件将显示以下由于interface
类型的事实而无法投放的类似数据:
The two print below m, _ := strct.Interface().(map[string]interface{})
will show the following similar data that i'm not able to cast due to the fact that are of interface
type:
[[2.049720 183.556 1.576323009e+09] [2.049750 555.125 1.576323009e+09] [2.049760 393.580 1.576323008e+09] [2.049980 206.514 1.576322995e+09]]
但是我无法解组数据.
所以我尝试使用@chmike
提供的其他功能:
So i've tried with a different function provided by @chmike
:
// UnmarshalJSON decode a BifinexOrder.
func UnmarshalJSON(data []byte) (datastructure.BitfinexOrder, error) {
var packedData []json.Number
var order datastructure.BitfinexOrder
err := json.Unmarshal(data, &packedData)
if err != nil {
return order, err
}
order.Price = packedData[0].String()
order.Volume = packedData[1].String()
t, err := packedData[2].Int64()
if err != nil {
return order, err
}
order.Timestamp = time.Unix(t, 0)
return order, nil
}
但是我收到以下错误:
json: cannot unmarshal array into Go value of type json.Number
一些提示?
注意 :我的先前问题已作为解组切片中2个不同结构"的副本而关闭.但是,如果您阅读了这些问题,那么我就不会处理两种不同的结构...我正在处理的json包含一个我以前不知道的键.我也无法封送BitfinexOrder
推荐答案
从@mkopriva和@chmike找到的解决方案:
Solution found from @mkopriva and @chmike:
谢谢你们!
package main
import (
"fmt"
"time"
"encoding/json"
)
var data = []byte(`{
"error": [],
"result": {
"LINKUSD": {
"asks": [
["2.049720", "183.556", 1576323009],
["2.049750", "555.125", 1576323009],
["2.049760", "393.580", 1576323008],
["2.049980", "206.514", 1576322995]
],
"bids": [
["2.043800", "20.691", 1576322350],
["2.039080", "755.396", 1576323007],
["2.036960", "214.621", 1576323006],
["2.036930", "700.792", 1576322987]
]
}
}
}`)
type Response struct {
Error []interface{} `json:"error"`
Result map[string]Order `json:"result"`
}
type Order struct {
Asks []BitfinexOrder `json:"asks"`
Bids []BitfinexOrder `json:"bids"`
}
type BitfinexOrder struct {
Price string
Volume string
Timestamp time.Time
}
// UnmarshalJSON decode a BifinexOrder.
func (b *BitfinexOrder) UnmarshalJSON(data []byte) error {
var packedData []json.Number
err := json.Unmarshal(data, &packedData)
if err != nil {
return err
}
b.Price = packedData[0].String()
b.Volume = packedData[1].String()
t, err := packedData[2].Int64()
if err != nil {
return err
}
b.Timestamp = time.Unix(t, 0)
return nil
}
func main() {
res := &Response{}
if err := json.Unmarshal(data, res); err != nil {
panic(err)
}
for key, value := range res.Result {
fmt.Println(key)
for i, ask := range value.Asks {
fmt.Printf("Asks[%d] = %#v\n", i, ask)
}
for i, bid := range value.Bids {
fmt.Printf("Bids[%d] = %#v\n", i, bid)
}
}
}
这篇关于解封没有密钥的嵌套json的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!