Go语言JSON转换陷阱:整数转浮点数

0 下载量 55 浏览量 更新于2024-08-31 收藏 199KB PDF 举报
"Go语言中进行JSON转换时可能会遇到的问题及解决方案" 在使用Go语言进行开发时,JSON转换是常见的操作,特别是在数据交互和序列化过程中。Go的标准库`encoding/json`提供了方便的API用于JSON与结构体间的转换。然而,在实际应用中,我们可能会遇到一些意料之外的问题,本文将探讨其中的一个主要问题:整数和浮点数转换不准确。 首先,我们来看一个例子,定义了一个`Person`结构体,包含`Age`(int64)和`Weight`(float64)字段。通过`json.Marshal`将`Person`结构体转换为JSON字符串,再使用`json.Unmarshal`将JSON解析为`map[string]interface{}`。问题在于,当将解析后的JSON对象强制转换为`map[string]interface{}`后,原本的`Age`(整数)和`Weight`(浮点数)都被转换成了`float64`类型。 ```go type Person struct { Name string Age int64 Weight float64 } func main() { person := Person{ Name: "WangWu", Age: 30, Weight: 150.07, } jsonBytes, _ := json.Marshal(person) var personFromJSON interface{} json.Unmarshal(jsonBytes, &personFromJSON) r := personFromJSON.(map[string]interface{}) fmt.Println(reflect.TypeOf(r["Age"]).Name()) // float64 fmt.Println(reflect.TypeOf(r["Weight"]).Name()) // float64 } ``` 这个问题的原因在于JSON规范中没有区分整数和浮点数,所有的数值都被视为同一类型,即浮点数。因此,Go的`json.Unmarshal`函数会将所有数字转换为最接近的浮点类型,即`float64`。这可能造成数据精度丢失,尤其是对于大整数而言。 为了解决这个问题,`encoding/json`包提供了一种方式,可以保留原始的整数类型,即使用`json.Number`。`json.Number`是一个字符串类型,它允许JSON的数字在Go中保持原始的文本形式,直到需要进行数值计算时才进行转换。 ```go import ( "encoding/json" "fmt" ) type Person struct { Name string `json:"name"` Age json.Number `json:"age"` Weight float64 `json:"weight"` } func main() { person := Person{ Name: "WangWu", Age: json.Number("30"), Weight: 150.07, } jsonBytes, _ := json.Marshal(person) var personFromJSON map[string]json.RawMessage json.Unmarshal(jsonBytes, &personFromJSON) age, _ := personFromJSON["age"].(json.Number).Int64() fmt.Println(age) // 30 (int64类型) } ``` 通过使用`json.Number`,我们可以确保`Age`字段在解析后仍保持其原始的整数形式,并且可以根据需要转换为适当的整数类型,而不会丢失精度。这样,我们就成功地避免了整数被错误地转换为浮点数的问题。 总结来说,Go语言在进行JSON转换时需要注意数字类型的处理。默认情况下,`json.Unmarshal`会将所有数字转换为`float64`,可能导致精度问题。通过使用`json.Number`,我们可以保留原始的数字格式,从而确保数据的准确性。在处理JSON与结构体之间的转换时,理解这些细节是至关重要的,有助于提高代码的健壮性和数据的完整性。