停止 json.Marshal() 从浮点数中去除尾随零

Nic*_*ode 6 json marshalling go

我遇到了以下问题:我的 golang 程序将一些信息转换为 JSON。例如,它会生成以下 json:

{
   "value":40,
   "unit":"some_string"
}
Run Code Online (Sandbox Code Playgroud)

问题是值的“输入”是 40.0 并且编组去除了尾随零。如果读取 JSON 的 EPL 能够在没有 .0 的情况下将 40 读取为浮点数,那将没有问题

因此 JSON 输出应如下所示:

{
   "value":40.0,
   "unit":"some_string"
}
Run Code Online (Sandbox Code Playgroud)

是否有可能“阻止” json.Marshal() 删除零?

编辑:值必须是浮点数

Mad*_*bat 7

@icza 提供了一个很好的答案,但只是为了提供另一种选择,您可以定义自己的浮点类型并为其定义自己的序列化。像这样

type KeepZero float64

func (f KeepZero) MarshalJSON() ([]byte, error) {
    if float64(f) == float64(int(f)) {
        return []byte(strconv.FormatFloat(float64(f), 'f', 1, 32)), nil
    }
    return []byte(strconv.FormatFloat(float64(f), 'f', -1, 32)), nil
}

type Pt struct {
    Value KeepZero
    Unit  string
}

func main() {
    data, err := json.Marshal(Pt{40.0, "some_string"})
    fmt.Println(string(data), err)
}
Run Code Online (Sandbox Code Playgroud)

这导致{"Value":40.0,"Unit":"some_string"} <nil>. 在操场上看看。


icz*_*cza 5

默认情况下,浮点数呈现时不带小数点和分数,如果其值为整数值。表示较短,表示相同的数字。

如果要控制数字在 JSON 表示中的显示方式,请使用json.Number类型。

例子:

type Pt struct {
    Value json.Number
    Unit  string
}

func main() {
    data, err := json.Marshal(Pt{json.Number("40.0"), "some_string"})
    fmt.Println(string(data), err)
}
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

{"Value":40.0,"Unit":"some_string"} <nil>
Run Code Online (Sandbox Code Playgroud)

如果你有一个数字作为float64值,你可以把它转换成json.Number这样:

func toNumber(f float64) json.Number {
    var s string
    if f == float64(int64(f)) {
        s = fmt.Sprintf("%.1f", f) // 1 decimal if integer
    } else {
        s = fmt.Sprint(f)
    }
    return json.Number(s)
}
Run Code Online (Sandbox Code Playgroud)

测试它:

f := 40.0
data, err := json.Marshal(Pt{toNumber(f), "some_string"})
fmt.Println(string(data), err)

f = 40.123
data, err = json.Marshal(Pt{toNumber(f), "some_string"})
fmt.Println(string(data), err)
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

{"Value":40.0,"Unit":"some_string"} <nil>
{"Value":40.123,"Unit":"some_string"} <nil>
Run Code Online (Sandbox Code Playgroud)

另一个方向,如果你想要 a 的float64json.Number,只需调用它的Number.Float64()方法。