Home > Software design >  How to render a byte array as a string in YAML in Go?
How to render a byte array as a string in YAML in Go?

Time:09-28

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 unmarshal-er output it as a string instead of a byte array? E.g.:

PublicKey: WXYZ

CodePudding user response:

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]}
  •  Tags:  
  • go
  • Related