我正在Go中处理一个json POST,其中包含一个包含64位整数的对象数组。当使用json.Unmarshal时,这些值似乎被转换为float64,并不是很有用。
body := []byte(`{"tags":[{"id":4418489049307132905},{"id":4418489049307132906}]}`) var dat map[string]interface{} if err := json.Unmarshal(body, &dat); err != nil { panic(err) } tags := dat["tags"].([]interface{}) for i, tag := range tags { fmt.Println("tag: ", i, " id: ", tag.(map[string]interface{})["id"].(int64)) }
有什么办法可以在json.Unmarshal的输出中保留原始的int64?
转到上面代码的游乐场
解决方案1
您可以使用Decoder和UseNumber解码您的号码而不会丢失:
该Number类型的定义如下:
Number
// A Number represents a JSON number literal. type Number string
这意味着您可以轻松地将其转换:
package main import ( "encoding/json" "fmt" "bytes" "strconv" ) func main() { body := []byte("{\"tags\":[{\"id\":4418489049307132905},{\"id\":4418489049307132906}]}") dat := make(map[string]interface{}) d := json.NewDecoder(bytes.NewBuffer(body)) d.UseNumber() if err := d.Decode(&dat); err != nil { panic(err) } tags := dat["tags"].([]interface{}) n := tags[0].(map[string]interface{})["id"].(json.Number) i64, _ := strconv.ParseUint(string(n), 10, 64) fmt.Println(i64) // prints 4418489049307132905 }
解决方案2
您还可以解码为适合您需求的特定结构:
package main import ( "encoding/json" "fmt" ) type A struct { Tags []map[string]uint64 // "tags" } func main() { body := []byte("{\"tags\":[{\"id\":4418489049307132905},{\"id\":4418489049307132906}]}") var a A if err := json.Unmarshal(body, &a); err != nil { panic(err) } fmt.Println(a.Tags[0]["id"]) // logs 4418489049307132905 }
就我个人而言,我通常更喜欢这种解决方案,它感觉更结构化且易于维护。
警告
如果您使用JSON,因为您的应用程序部分是在JavaScript中的,请注意:JavaScript没有64位整数,只有一个数字类型,即IEEE754双精度浮点数。因此,您将无法使用标准解析功能在JavaScript中解析此JSON而不会丢失。