【问题标题】:preserve int64 values when parsing json in Go在 Go 中解析 json 时保留 int64 值
【发布时间】:2013-06-05 17:33:00
【问题描述】:

我正在 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?

Go Playground of above code

【问题讨论】:

    标签: json parsing go


    【解决方案1】:

    解决方案 1

    您可以使用DecoderUseNumber 解码您的号码而不会丢失:

    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。

    【讨论】:

      【解决方案2】:

      更简单的一个:

      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.Printf("tag: %v, id: %.0f", i, tag.(map[string]interface{})["id"].(float64))
      }
      

      【讨论】:

      • 此解决方案的输出错误,因为两个 id 都更改为 4418489049307132928。
      【解决方案3】:

      我意识到这已经很老了,但这是我最终使用的解决方案

      /* 
         skipping previous code, this is just converting the float 
         to an int, if the value is the same with or without what's 
         after the decimal points
      */
      
      f := tag.(map[string]interface{})["id"].(float64)
      if math.Floor(f) == f {
        fmt.Println("int tag: ", i, " id: ", int64(f))    
      } else {
        fmt.Println("tag: ", i, " id: ", f)
      }
      

      【讨论】:

        猜你喜欢
        • 2012-06-15
        • 2014-09-20
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 2015-08-07
        • 1970-01-01
        • 1970-01-01
        • 2015-10-13
        相关资源
        最近更新 更多