我遇到了以下问题:我的golang程序将一些信息转换为JSON。例如,它会产生以下json:
{
"value":40,
"unit":"some_string"
}
问题是值的“输入”为40.0,编组去掉尾随为零。如果读取JSON的EPL能够在不使用.0的情况下读取40作为浮点,那就没有问题了
因此,JSON输出应该如下所示:
{
"value":40.0,
"unit":"some_string"
}
是否有可能“阻止”json.Marshal()移除零?
编辑:值必须是浮点数
发布于 2018-09-21 15:41:30
@icza提供了一个很好的答案,但是为了提供另一个选项,您可以定义自己的float类型,并为它定义自己的序列化。像这样
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)
}
这导致了{"Value":40.0,"Unit":"some_string"} <nil>
。去操场看看。
发布于 2018-09-21 15:25:18
默认情况下,如果浮点数是整数值,则不使用小数点和分数来呈现浮点数。表示更短,表示相同的数字。
如果希望控制数字在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)
}
输出(在围棋游乐场上尝试):
{"Value":40.0,"Unit":"some_string"} <nil>
如果有一个数字作为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)
}
测试它:
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)
输出(在围棋游乐场上尝试):
{"Value":40.0,"Unit":"some_string"} <nil>
{"Value":40.123,"Unit":"some_string"} <nil>
另一个方向,如果您想要一个json.Number
的json.Number
值,只需调用它的Number.Float64()
方法。
发布于 2018-10-25 19:38:01
我也遇到了类似的问题,我想将一个map[string]interface{}
的浮点数f.x 1.0
封送到JSON作为1.0
。我通过为自定义浮点数类型添加一个自定义Marshal函数来解决这个问题,然后将映射中的浮点数替换为自定义类型:
type customFloat float64
func (f customFloat) MarshalJSON() ([]byte, error) {
if float64(f) == math.Trunc(float64(f)) {
return []byte(fmt.Sprintf("%.1f", f)), nil
}
return json.Marshal(float64(f))
}
func replaceFloat(value map[string]interface{}) {
for k, v := range value {
switch val := v.(type) {
case map[string]interface{}:
replaceFloat(val)
case float64:
value[k] = customFloat(val)
}
}
}
然后替换所有float64节点:
replaceFloat(myValue)
bytes, err := json.Marshal(myValue)
这将打印像1.0
这样的浮点数。
https://stackoverflow.com/questions/52446730
复制相似问题