为什么 YAML.v3 不编组基于 golang 中的 String() 的结构?

我有一个包含基于枚举的类型的结构。我正在尝试将其呈现为用户友好的字符串。这是最小可行代码:


package main


import (

    "fmt"


    "gopkg.in/yaml.v3"

)


type Job struct {

    Engine Engine `json:"Engine" yaml:"Engine"`

}


//go:generate stringer -type=Engine --trimprefix=Engine

type Engine int


const (

    engineUnknown Engine = iota // must be first

    EngineDocker

    engineDone // must be last

)


func main() {

    j := Job{Engine: EngineDocker}


    fmt.Printf("%+v\n\n", j)

    out, _ := yaml.Marshal(j)

    fmt.Println(string(out))

}

这是生成的代码:


// Code generated by "stringer -type=Engine --trimprefix=Engine"; DO NOT EDIT.


package main


import "strconv"


func _() {

    // An "invalid array index" compiler error signifies that the constant values have changed.

    // Re-run the stringer command to generate them again.

    var x [1]struct{}

    _ = x[engineUnknown-0]

    _ = x[EngineDocker-1]

    _ = x[engineDone-2]

}


const _Engine_name = "engineUnknownDockerengineDone"


var _Engine_index = [...]uint8{0, 13, 19, 29}


func (i Engine) String() string {

    if i < 0 || i >= Engine(len(_Engine_index)-1) {

        return "Engine(" + strconv.FormatInt(int64(i), 10) + ")"

    }

    return _Engine_name[_Engine_index[i]:_Engine_index[i+1]]

}

这是输出:


{Engine:1}


Engine: 1

这是我想要的输出:


{Engine:Docker}


Engine: Docker

我认为生成文件中的 String() 可以完成此操作。有什么办法吗?谢谢!


喵喔喔
浏览 167回答 1
1回答

隔江千里

yaml封送拆收器不使用String方法。相反,YAML使用&nbsp;encoding.TextMarshaler和encoding.TextUnmarshaler接口。实际上,所有其他编解码器方案——JSON、XML、TOML 等——都使用这些接口来读取/写入值。因此,如果您为您的类型实现这些方法,您将免费获得所有其他编解码器。这是一个如何为您的枚举制作人类可读编码的示例:https://go.dev/play/p/pEcBmAM-oZJtype Engine intconst (&nbsp; &nbsp; engineUnknown Engine = iota // must be first&nbsp; &nbsp; EngineDocker&nbsp; &nbsp; engineDone // must be last)var engineNames []stringvar engineNameToValue map[string]Enginefunc init() {&nbsp; &nbsp; engineNames = []string{"Unknown", "Docker"}&nbsp; &nbsp; engineNameToValue = make(map[string]Engine)&nbsp; &nbsp; for i, name := range engineNames {&nbsp; &nbsp; &nbsp; &nbsp; engineNameToValue[strings.ToLower(name)] = Engine(i)&nbsp; &nbsp; }}func (e Engine) String() string {&nbsp; &nbsp; if e < 0 || int(e) >= len(engineNames) {&nbsp; &nbsp; &nbsp; &nbsp; panic(fmt.Errorf("Invalid engine code: %d", e))&nbsp; &nbsp; }&nbsp; &nbsp; return engineNames[e]}func ParseEngine(text string) (Engine, error) {&nbsp; &nbsp; i, ok := engineNameToValue[strings.ToLower(text)]&nbsp; &nbsp; if !ok {&nbsp; &nbsp; &nbsp; &nbsp; return engineUnknown, fmt.Errorf("Invalid engine name: %s", text)&nbsp; &nbsp; }&nbsp; &nbsp; return i, nil}func (e Engine) MarshalText() ([]byte, error) {&nbsp; &nbsp; return []byte(e.String()), nil}func (e *Engine) UnmarshalText(text []byte) (err error) {&nbsp; &nbsp; name := string(text)&nbsp; &nbsp; *e, err = ParseEngine(name)&nbsp; &nbsp; return}怎么运行的:func main() {&nbsp; &nbsp; j := Job{Engine: EngineDocker}&nbsp; &nbsp; fmt.Printf("%#v\n\n", j)&nbsp; &nbsp; out, err := yaml.Marshal(j)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("YAML: %s\n", string(out))&nbsp; &nbsp; var jj Job&nbsp; &nbsp; err = yaml.Unmarshal(out, &jj)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("%#v\n\n", jj)&nbsp; &nbsp; // == JSON ==&nbsp; &nbsp; out, err = json.Marshal(j)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("JSON: %s\n", string(out))&nbsp; &nbsp; var jjs Job&nbsp; &nbsp; err = json.Unmarshal(out, &jjs)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; }&nbsp; &nbsp; fmt.Printf("%#v\n\n", jjs)}输出main.Job{Engine:1}YAML: Engine: Dockermain.Job{Engine:1}JSON: {"Engine":"Docker"}main.Job{Engine:1}看?它无需任何额外工作即可将字符串写入 YAML 和 JSON 并从中读取。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go