解封没有密钥的嵌套json [英] Unmarshal a nested json without a key

查看:74
本文介绍了解封没有密钥的嵌套json的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不是不能从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数据,我能够检索包含asksbids列表的接口.

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆