我有一个结构。
id
可以作为字符串或数字。为了处理它,我将其类型指定为 interface
。
type Request struct {
Id interface{} `json:"id"`
Code string `json:"code"`
}
据我了解,如果输入一个数字,它会转换为
float64
,但这会导致准确性损失。我需要将其转换为int64
,但我不明白如何在不损失准确性的情况下做到这一点
func main() {
jsonData := []byte(`{"id": 123456789123456789, "code":"123"}`)
var request Request
err := json.Unmarshal(jsonData, &request)
if err != nil {
fmt.Println("Error JSON:", err)
return
}
if value, ok := request.Id.(int64); ok {
fmt.Println("Result:", value)
} else {
fmt.Printf("Error. Type: %T", value)
}
//Output: Error. Type: int64
res := int64(request.Id.(float64))
fmt.Println(res)
//Output:123456789123456784. Expected: 123456789123456789
}
当您将 JSON 数据解组到 Go 中具有
interface{}
类型的字段时,解组的值通常存储为基本 JSON 类型之一(string
、float64
、bool
、map[string]interface{}
、[]interface{}
)
或 nil
)。在您的情况下,当您解组一个大整数时,它会存储为 float64
,并且您会遇到精度损失,因为 float64
无法以完美的精度表示非常大的整数。
要解决此问题并将 JSON 数据解组为
int64
,您可以在解组后对 interface{}
值执行类型断言以检查其基础类型。如果它是 float64
,您可以将其转换为 int64
。您可以通过以下方式修改代码来实现此目的:
package main
import (
"encoding/json"
"fmt"
)
type Request struct {
Id interface{} `json:"id"`
Code string `json:"code"`
}
func main() {
jsonData := []byte(`{"id": 123456789123456789, "code":"123"}`)
var request Request
err := json.Unmarshal(jsonData, &request)
if err != nil {
fmt.Println("Error JSON:", err)
return
}
switch v := request.Id.(type) {
case float64:
res := int64(v)
fmt.Println("Result:", res)
case string:
// If it's a string, you can try parsing it as an int64
res, parseErr := strconv.ParseInt(v, 10, 64)
if parseErr != nil {
fmt.Println("Error parsing string as int64:", parseErr)
} else {
fmt.Println("Result:", res)
}
default:
fmt.Printf("Error. Unexpected type: %T", v)
}
}
在此代码中,我们使用类型开关来检查解组后
Id
字段的类型。如果它是 float64
,我们将其转换为 int64
。如果它是 string
,我们尝试将其解析为 int64
。这样,您就可以正确处理这两种情况而不会损失精度。