Go语言 解组yaml时保持精度

ovfsdjhp  于 2022-12-07  发布在  Go
关注(0)|答案(1)|浏览(125)

我得到了这个代码:

package main

import (
 "fmt"

 "gopkg.in/yaml.v2"
)

func main() {
 kkk := "common:\n vartest1: 1.2000\n vartest2: 1.22233"
 tmp := map[string]interface{}{}
 yaml.Unmarshal([]byte(kkk), tmp)

 fmt.Println(tmp)

}

我所期望的是浮点数的精度与字符串保持一致。但我得到了以下输出:

map[common:map[vartest1:1.2 vartest2:1.22233]]

我试过这个:

package main

import (
 "fmt"

 "gopkg.in/yaml.v2"
)

type Myfloat64 float64

func (e *Myfloat64) UnmarshalYAML(unmarshal func(interface{}) error) error {
 var test Myfloat64
 err := unmarshal(&test)
 if err != nil {
  return err
 }

 fmt.Println(test)

 *e = test

 return nil
}

func main() {
 kkk := "common:\n vartest1: 1.2000\n vartest2: 1.22233"
 tmp := map[string]interface{}{}
 yaml.Unmarshal([]byte(kkk), tmp)

 fmt.Println(tmp)

}

但是UnmarshalYAML还没有被调用,因为类型Myfloat64不在map[string]interface{}{}中。我必须确保map[string]interface{}{}不变,因为我不能有一个固定的结构来定义未封送的结构。
是否有办法保持精度?输入必须是“common:\n vartest1:1.2000\n变量测试2:1.22233”。不允许将1.2000更新为字符串。

kyxcudwk

kyxcudwk1#

有没有办法保持精度?
不要将字符串解析为float,而是保留原始值,即保留string
下面是一个例子:

  • 注意#1:代码需要扩展以处理其他类型。
  • 注意#2:这是使用yaml.v3
type Any struct {
    Val any
}

func (a Any) String() string {
    return fmt.Sprint(a.Val)
}

func (a *Any) UnmarshalYAML(n *yaml.Node) error {
    switch n.Kind {
    case yaml.MappingNode:
        m := map[string]Any{}
        if err := n.Decode(&m); err != nil {
            return err
        }
        a.Val = m
    case yaml.ScalarNode:
        switch n.Tag {
        case "!!float":
            // Don't parse the raw string value,
            // use it as is if you want to retain
            // its formatting.
            a.Val = n.Value
        }
    }
    return nil
}

playground上试试。

# output:
map[common:map[vartest1:1.2000 vartest2:1.22233]]

相关问题