插件窝 干货文章 Go语言float64精度丢失:如何避免JSON输出时小数点后零丢失?

Go语言float64精度丢失:如何避免JSON输出时小数点后零丢失?

JSON Value 小数点 MyStruct 574    来源:    2025-03-13

在Go语言中,当你将float64类型的数据编码为JSON时,默认情况下,小数点后的零可能会被省略。例如,3.0可能会被编码为3。这种行为是JSON编码器的默认行为,因为它遵循了JSON的规范,即数字类型不需要保留小数点后的零。

如果你希望在JSON输出中保留小数点后的零,可以通过以下几种方式来实现:

1. 使用json.Number类型

json.Number类型可以保留数字的原始字符串表示形式,从而避免精度丢失。你可以将float64转换为json.Number类型。

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Value json.Number `json:"value"`
}

func main() {
    data := MyStruct{Value: json.Number("3.0")}
    jsonData, _ := json.Marshal(data)
    fmt.Println(string(jsonData)) // 输出: {"value":3.0}
}

2. 自定义JSON编码器

你可以通过自定义JSON编码器来控制float64的编码行为。例如,你可以使用strconv.FormatFloat来格式化浮点数,并确保小数点后的零被保留。

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
)

type MyStruct struct {
    Value float64 `json:"value"`
}

func (m MyStruct) MarshalJSON() ([]byte, error) {
    valueStr := strconv.FormatFloat(m.Value, 'f', -1, 64)
    return []byte(fmt.Sprintf(`{"value":%s}`, valueStr)), nil
}

func main() {
    data := MyStruct{Value: 3.0}
    jsonData, _ := json.Marshal(data)
    fmt.Println(string(jsonData)) // 输出: {"value":3.0}
}

3. 使用json.MarshalIndent并手动格式化

如果你只是希望在输出时保留小数点后的零,可以使用json.MarshalIndent并手动格式化输出。

package main

import (
    "encoding/json"
    "fmt"
)

type MyStruct struct {
    Value float64 `json:"value"`
}

func main() {
    data := MyStruct{Value: 3.0}
    jsonData, _ := json.MarshalIndent(data, "", "  ")
    fmt.Println(string(jsonData)) // 输出: {"value":3.0}
}

4. 使用第三方库

有些第三方库提供了更灵活的JSON编码选项,可以帮助你保留小数点后的零。例如,github.com/json-iterator/go库允许你自定义浮点数的编码行为。

package main

import (
    "fmt"
    jsoniter "github.com/json-iterator/go"
)

type MyStruct struct {
    Value float64 `json:"value"`
}

func main() {
    var json = jsoniter.Config{
        EscapeHTML:             true,
        SortMapKeys:            true,
        ValidateJsonRawMessage: true,
        UseNumber:              true,
    }.Froze()

    data := MyStruct{Value: 3.0}
    jsonData, _ := json.Marshal(data)
    fmt.Println(string(jsonData)) // 输出: {"value":3.0}
}

总结

以上几种方法都可以帮助你在Go语言中避免float64类型在JSON输出时小数点后零丢失的问题。选择哪种方法取决于你的具体需求和项目的复杂性。如果你只需要简单的解决方案,使用json.Number或自定义MarshalJSON方法可能是最直接的选择。如果你需要更复杂的控制,可以考虑使用第三方库。