英文:
How to render a byte array as a string in YAML in Go?
问题
我有一个包含字节数组字段的结构体。以下是代码:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
type A struct {
PublicKey []byte `json:"PublicKey" yaml:"PublicKey"`
}
// 实现 yaml 包的 Marshaler 接口
func (a A) MarshalYAML() (interface{}, error) {
type alias A
node := yaml.Node{}
_ = node.Encode(alias(a))
return node, nil
}
func PublicKey() {
token := []byte{87, 88, 89, 90}
a := A{PublicKey: token}
fmt.Printf("A: %+v\nA.PublicKey:%s\n\n", a, a.PublicKey)
out, _ := yaml.Marshal(a)
fmt.Println(string(out))
}
func main() {
PublicKey()
}
以下是输出结果:
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
PublicKey:
- 87
- 88
- 89
- 90
是否可能将其输出为字符串而不是字节数组?例如:
PublicKey: WXYZ
英文:
I have a struct with a byte array as a field. Here's the code:
package main
import (
"fmt"
"gopkg.in/yaml.v3"
)
type A struct {
PublicKey []byte `json:"PublicKey" yaml:"PublicKey"`
}
// Implements the Marshaler interface of the yaml pkg.
func (a A) MarshalYAML() (interface{}, error) {
type alias A
node := yaml.Node{}
_ = node.Encode(alias(a))
return node, nil
}
func PublicKey() {
token := []byte{87, 88, 89, 90}
a := A{PublicKey: token}
fmt.Printf("A: %+v\nA.PublicKey:%s\n\n", a, a.PublicKey)
out, _ := yaml.Marshal(a)
fmt.Println(string(out))
}
func main() {
PublicKey()
}
Here's the output:
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
PublicKey:
- 87
- 88
- 89
- 90
Is it possible to have the marshal-er output it as a string instead of a byte array? E.g.:
PublicKey: WXYZ
答案1
得分: 2
// 对于 `A`,我更倾向于为公钥创建自定义类型,并使用Base64对其值进行编码/解码,而不是自定义编解码器
type PubKey []byte
func (pk PubKey) MarshalYAML() (interface{}, error) {
return base64.StdEncoding.EncodeToString(pk), nil
}
func (pk *PubKey) UnmarshalYAML(node *yaml.Node) error {
value := node.Value
ba, err := base64.StdEncoding.DecodeString(value)
if err != nil {
return err
}
*pk = ba
return nil
}
type A struct {
PublicKey PubKey `json:"PublicKey" yaml:"PublicKey"`
}
// 没有自定义的YAML编解码器
// 编码/解码示例:
func PublicKey() {
token := []byte{87, 88, 89, 90}
a := A{PublicKey: token}
fmt.Printf("A: %+v\nA.PublicKey:%s\n\n", a, a.PublicKey)
out, _ := yaml.Marshal(a)
fmt.Println("Encoded: ", string(out))
var b A
err := yaml.Unmarshal(out, &b)
if err != nil {
println(err)
}
fmt.Printf("解码后: %+v\n", b)
}
完整示例:https://go.dev/play/p/2_gMi9sazIp
结果为:
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
Encoded: PublicKey: V1hZWg==
解码后: {PublicKey:[87 88 89 90]}
顺便提一下,Base64是[JSON编解码器如何对字节切片进行编码][1]
使用你的数据的示例:https://go.dev/play/p/dGr0i0DnnNX
结果为:
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
Encoded JSON: {"PublicKey":"V1hZWg=="}
解码后 JSON: {PublicKey:[87 88 89 90]}
英文:
Instead of customizing codec for A
I'd rather make custom type for the public key and use Base64 to encode/decode its value
type PubKey []byte
func (pk PubKey) MarshalYAML() (interface{}, error) {
return base64.StdEncoding.EncodeToString(pk), nil
}
func (pk *PubKey) UnmarshalYAML(node *yaml.Node) error {
value := node.Value
ba, err := base64.StdEncoding.DecodeString(value)
if err != nil {
return err
}
*pk = ba
return nil
}
type A struct {
PublicKey PubKey `json:"PublicKey" yaml:"PublicKey"`
}
// No custom YAML codec
Coding/decoding goes like this:
func PublicKey() {
token := []byte{87, 88, 89, 90}
a := A{PublicKey: token}
fmt.Printf("A: %+v\nA.PublicKey:%s\n\n", a, a.PublicKey)
out, _ := yaml.Marshal(a)
fmt.Println("Encoded: ", string(out))
var b A
err := yaml.Unmarshal(out, &b)
if err != nil {
println(err)
}
fmt.Printf("after decoding: %+v\n", b)
}
Full example https://go.dev/play/p/2_gMi9sazIp
The result is:
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
Encoded: PublicKey: V1hZWg==
after decoding: {PublicKey:[87 88 89 90]}
BTW, base64 is how json
codec marshals byte slices
Example with your data: https://go.dev/play/p/dGr0i0DnnNX
A: {PublicKey:[87 88 89 90]}
A.PublicKey:WXYZ
Encoded JSON: {"PublicKey":"V1hZWg=="}
after decoding JSON: {PublicKey:[87 88 89 90]}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论