Golang JSON数组中不同类型的反射:float64与int64

huangapple go评论97阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2015年5月7日 23:35:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/30105688.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定