Following up on Keys are always lowercase? #923,
I'm looking for the easiest way for me to unmarshal an unstructured yaml into GolangCasing keys. Details --
Take a look at
https://go.dev/play/p/nIhDqoRpeK1
I.e.,
package main
import (
"fmt"
"log"
"gopkg.in/yaml.v3"
)
var data = `
a: Easy!
b:
c: 2
d: [3, 4]
`
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct {
A string
B struct {
RenamedC int `yaml:"c"`
D []int `yaml:",flow"`
}
}
func main() {
m := make(map[interface{}]interface{})
err := yaml.Unmarshal([]byte(data), &m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m:\n%v\n\n", m)
d, err := yaml.Marshal(&m)
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("--- m dump:\n%s\n\n", string(d))
}
m
.One follow up comment says that they "are switching from gopkg.in/yaml.v3 to sigs.k8s.io/yaml", but reading the docs of sigs.k8s.io/yaml, it looks to me that they still need to know the structure of yaml, and have also need to define the translation mechanism ahead of the time.
Is there any easy way to unmarshal unstructured yaml as uppercase / GolangCasing keys? What's the easiest way to do that? If no Go packages are providing such functionality out of the box, then is any of them have plugin/callbacks that allow me to easily do the translation myself?
You can declare a custom key type that implements the yaml.Unmarshaler
interface.
Something like this:
type MyKey string
func (k *MyKey) UnmarshalYAML(n *yaml.Node) error {
var s string
if err := n.Decode(&s); err != nil {
return err
}
*k = MyKey(strings.ToUpper(s))
return nil
}
And then use it as the map's key.
m := make(map[MyKey]any)