当解析 JSON 数据时,默认将数值当做哪种类型?

参考回答

在 Golang 中,当解析 JSON 数据时,默认会将数值解析为 float64 类型。这是因为 JSON 的数字类型不区分整数和浮点数,而 Go 的标准库 encoding/json 出于兼容性考虑,会将所有的数字解析为 float64


详细讲解与拓展

  1. 为什么是 float64
    • JSON 中的数字是以十进制表示的,不区分整数和浮点数,而 Go 语言的 JSON 解码器选择 float64 是因为它可以表示大多数常见的数字范围,且符合 IEEE 754 标准,适用于各种计算需求。

    示例:

    package main
    
    import (
       "encoding/json"
       "fmt"
    )
    
    func main() {
       jsonData := `{"number": 123}`
    
       var result map[string]interface{}
       if err := json.Unmarshal([]byte(jsonData), &result); err != nil {
           panic(err)
       }
    
       // 打印结果
       fmt.Printf("类型: %T, 值: %v\n", result["number"], result["number"])
    }
    
    Go

    输出:

    类型: float64, 值: 123
    
  2. 如何解析成其他类型?
    如果需要特定的类型(如 intfloat32),可以通过以下方法处理:

  • 使用结构体解码:
    定义字段类型明确的结构体,这样可以直接解析为所需类型:

    “`go
    package main

    import (
    "encoding/json"
    "fmt"
    )

    type Data struct {
    Number int <code>json:"number"</code>
    }

    func main() {
    jsonData := <code>{"number": 123}</code>

    <pre><code> var result Data
    if err := json.Unmarshal([]byte(jsonData), &result); err != nil {
    panic(err)
    }

    fmt.Printf("类型: %T, 值: %v\n", result.Number, result.Number)
    </code></pre>

    }

    “`
    输出:
    “`
    类型: int, 值: 123
    “`

  • 类型断言:
    如果使用 map[string]interface{} 解析,可以通过类型断言将 float64 转为其他类型:

    “`go
    number := result["number"].(float64) // 类型断言为 float64
    intNumber := int(number) // 转为 int 类型
    fmt.Println(intNumber) // 输出: 123
    “`

  1. 精度问题的注意事项:
    使用 float64 解析整数时,可能会导致精度问题。例如:

    jsonData := `{"largeNumber": 1234567890123456789}`
    
    var result map[string]interface{}
    json.Unmarshal([]byte(jsonData), &result)
    
    fmt.Printf("值: %v\n", result["largeNumber"])
    
    Go

    输出:

    值: 1.2345678901234568e+18
    

    对于超出 float64 精度的数字,可以通过 json.Number 来避免:

    import "encoding/json"
    
    decoder := json.NewDecoder(strings.NewReader(jsonData))
    decoder.UseNumber()
    var result map[string]interface{}
    decoder.Decode(&result)
    
    largeNumber, _ := result["largeNumber"].(json.Number).Int64()
    fmt.Println(largeNumber) // 精确解析
    
    Go

总结

  • 默认情况下,Go 的 JSON 解析器将数值解析为 float64 类型。
  • 如果需要特定类型,可以通过结构体解码或类型断言进行处理。
  • 对于大数值或高精度场景,可以使用 json.Number 避免精度问题。

通过理解这些机制,可以更灵活地处理 JSON 数据,同时避免常见的精度和类型问题。

发表评论

后才能评论