首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >停止json.Marshal()从浮点数中剥离尾随零点

停止json.Marshal()从浮点数中剥离尾随零点
EN

Stack Overflow用户
提问于 2018-09-21 15:16:59
回答 5查看 6.1K关注 0票数 6

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

代码语言:javascript
运行
复制
{
   "value":40,
   "unit":"some_string"
}

问题是值的“输入”为40.0,编组去掉尾随为零。如果读取JSON的EPL能够在不使用.0的情况下读取40作为浮点,那就没有问题了

因此,JSON输出应该如下所示:

代码语言:javascript
运行
复制
{
   "value":40.0,
   "unit":"some_string"
}

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

编辑:值必须是浮点数

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2018-09-21 15:41:30

@icza提供了一个很好的答案,但是为了提供另一个选项,您可以定义自己的float类型,并为它定义自己的序列化。像这样

代码语言:javascript
运行
复制
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>去操场看看。

票数 11
EN

Stack Overflow用户

发布于 2018-09-21 15:25:18

默认情况下,如果浮点数是整数值,则不使用小数点和分数来呈现浮点数。表示更短,表示相同的数字。

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

示例:

代码语言:javascript
运行
复制
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)
}

输出(在围棋游乐场上尝试):

代码语言:javascript
运行
复制
{"Value":40.0,"Unit":"some_string"} <nil>

如果有一个数字作为float64值,则可以将其转换为json.Number,如下所示:

代码语言:javascript
运行
复制
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)
}

测试它:

代码语言:javascript
运行
复制
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)

输出(在围棋游乐场上尝试):

代码语言:javascript
运行
复制
{"Value":40.0,"Unit":"some_string"} <nil>
{"Value":40.123,"Unit":"some_string"} <nil>

另一个方向,如果您想要一个json.Numberjson.Number值,只需调用它的Number.Float64()方法。

票数 5
EN

Stack Overflow用户

发布于 2018-10-25 19:38:01

我也遇到了类似的问题,我想将一个map[string]interface{}的浮点数f.x 1.0封送到JSON作为1.0。我通过为自定义浮点数类型添加一个自定义Marshal函数来解决这个问题,然后将映射中的浮点数替换为自定义类型:

代码语言:javascript
运行
复制
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节点:

代码语言:javascript
运行
复制
replaceFloat(myValue)
bytes, err := json.Marshal(myValue)

这将打印像1.0这样的浮点数。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52446730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档