英文:
Golang JSON array of different types reflection: float64 vs int64
问题
考虑以下简单示例:
package main
import (
"encoding/json"
"fmt"
"log"
"reflect"
)
var args = `[1, 2.5, "aaa", true, false]`
func main() {
var x []interface{}
err := json.Unmarshal([]byte(args), &x)
if err != nil {
log.Fatalf("%s", err.Error())
panic(fmt.Sprintf("%s", err.Error()))
}
for _, arg := range x {
t := reflect.TypeOf(arg).Kind().String()
v := reflect.ValueOf(arg)
if t == "int64" {
fmt.Printf("int64 %v\n", v.Int())
}
if t == "float64" {
fmt.Printf("float64 %v\n", v.Float())
}
if t == "string" {
fmt.Printf("string %v\n", v.String())
}
if t == "bool" {
fmt.Printf("bool %v\n", v.Bool())
}
}
}
程序输出:
float64 1
float64 2.5
string aaa
bool true
bool false
如你所见,我的输入是一个有效的 JSON,表示一个包含五个元素的数组:
- 整数
- 浮点数
- 字符串
- 布尔值
- 布尔值
当我将有效的 JSON 字符串解组为 []interface{} 并尝试使用反射检查类型时,JSON 中的整数值具有 float64 类型。有任何想法为什么会这样?这是预期的行为吗?
英文:
Consider this simple example:
package main
import (
"encoding/json"
"fmt"
"log"
"reflect"
)
var args = `[1, 2.5, "aaa", true, false]`
func main() {
var x []interface{}
err := json.Unmarshal([]byte(args), &x)
if err != nil {
log.Fatalf("%s", err.Error())
panic(fmt.Sprintf("%s", err.Error()))
}
for _, arg := range x {
t := reflect.TypeOf(arg).Kind().String()
v := reflect.ValueOf(arg)
if t == "int64" {
fmt.Printf("int64 %v\n", v.Int())
}
if t == "float64" {
fmt.Printf("float64 %v\n", v.Float())
}
if t == "string" {
fmt.Printf("string %v\n", v.String())
}
if t == "bool" {
fmt.Printf("bool %v\n", v.Bool())
}
}
}
The program outputs:
float64 1
float64 2.5
string aaa
bool true
bool false
As you can see, my input is a valid JSON which represents an array with five items:
- integer
- floating point number
- string
- boolean
- boolean
When I unmarshal the valid JSON string into []interface{} and try to check the types with reflection, the integer value from JSON has a type of float64. Any idea why? Is this expected behaviour?
答案1
得分: 6
这是Unmarshal
的文档化行为。所有数字都会被解组为float64类型。
为了将JSON解组为接口值,Unmarshal会将以下类型存储在接口值中:
- bool,用于JSON布尔值
- float64,用于JSON数字
- string,用于JSON字符串
- []interface{},用于JSON数组
- map[string]interface{},用于JSON对象
- nil,用于JSON的null值
这是因为JSON没有整数类型,JSON中的每个数字都被定义为64位浮点数。
英文:
This is documented behavior of Unmarshal
. All numbers are unmarshaled into float64.
> To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:
> - bool, for JSON booleans
- float64, for JSON numbers
- string, for JSON strings
- []interface{}, for JSON arrays
- map[string]interface{}, for JSON objects
- nil for JSON null
This is because JSON does not have integers, every number in JSON is defined to be a 64 bit floating point.
答案2
得分: 3
这是JSON解码器的默认行为。你可以通过使用UseNumber
方法将其更改为输出json.Number
。
英文:
This is the default behaviour of the JSON decoder. You can change it to output json.Number
instead by using the UseNumber
method.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论