简体   繁体   中英

How to Unmarshal list of varied types without defaulting to float64

I have the following json data (from an external program, simplified a bit) I can't change the json format.

[1416495600501595942, {"venue_id": 73, "message_type": "ABC", "sequence": 26686695}]

I'm having trouble unpacking it in Go, I think mostly because it's a list of disparate types. The obvious thing to do seems to be to do is []interface{}, which works, but in converts it to a float64, which produces a roundoff error that I can't deal with (the number is a timestamp since epoch in nanos).

I can get it to work by unpacking it twice, as []interface{} and []int64, but that's obviously going to hinder performance, and I'm processing large amounts of data in real time. I tried using struct here because that would get treated as a map, not a list[]

Is there any way to either pass it the format of the data, or make it default to int64 instead of float64? It's always going to be

[int64, map[string]interface{}]

ie I know the format of the upper level list, and that the keys of the map are strings, but the values could be anything (painfully, including decimals, which I think the only thing I can use to interpret them as is floats ...)

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    j := `[1416495600501595942, {"venue_id": 73, "message_type": "ABC", "sequence": 26686695}]`
    b := []byte(j)
    fmt.Println(j)
    var line []interface{}
    var ints []int64

    json.Unmarshal(b, &line)
    fmt.Println(line)
    // fmt.Println(line[0].(int64))  - this doesn't work
    fmt.Println(line[0].(float64))
    fmt.Println(int64(line[0].(float64)))

    json.Unmarshal(b, &ints)
    fmt.Println(ints)
}

Output is as follows:

[1416495600501595942, {"venue_id": 73, "message_type": "oKC", "sequence": 26686695}]
[1.416495600501596e+18 map[venue_id:73 message_type:oKC sequence:2.6686695e+07]]
1.416495600501596e+18
1416495600501595904
[1416495600501595942 0]

Solution (thanks to makpoc / dystroy)

package main

import (
    "encoding/json"
    "fmt"
    "bytes"
)

func main() {
    j := `[1416495600501595942, {"venue_id": 7.3, "message_type": "oKC", "sequence": 26686695}]`
    b := []byte(j)
    fmt.Println(j)
    var line []interface{}

    d := json.NewDecoder(bytes.NewBuffer(b))
    d.UseNumber()
        if err := d.Decode(&line); err != nil {
        panic(err)
    }
    fmt.Println(line[0])
    data := line[1].(map[string]interface{})
    fmt.Println(data["venue_id"])
    fmt.Println(data["sequence"])
}

根据此答案,您可以使用Decoder->和UseNumber或结构来代替直接解析值。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM