mapstructure
mapstructure copied to clipboard
Tag rename missing is encoding
If I'm not mistaken, the main.go below should output:
sub_config:
first_children:
- name: parent
grand_children:
- name: foo
- name: bar
Instead, it is outputting:
sub_config:
first_children:
- name: parent
children:
- name: foo
- name: bar
Notice that the second slice is intended to be named grand_children but is really being named children as it is actually named in the struct.
If I step through the mapstructure.Decode function, I can see the tag get read and build an appropriate fieldName as sub_config.first_children[0].grand_children, but that at some point gets shuffled back to children.
We can see in this screenshot the result of the Decode prior to rendering the yaml:

main.go
package main
import (
"fmt"
"os"
"github.com/mitchellh/mapstructure"
"gopkg.in/yaml.v3"
)
type Config struct {
Subconfig SubSection `mapstructure:"sub_config"`
}
type SubSection struct {
Children []Child `mapstructure:"first_children"`
}
type Child struct {
Name string
Children []Grandchild `mapstructure:"grand_children"`
}
type Grandchild struct {
Name string
}
func main() {
config := &Config{
Subconfig: SubSection{
Children: []Child{
{Name: "parent", Children: []Grandchild{
{Name: "foo"},
{Name: "bar"},
}},
},
},
}
encodedData := map[string]interface{}{}
err := mapstructure.Decode(config, &encodedData)
if err != nil {
err = fmt.Errorf("unable to encode configuration: %w", err)
fmt.Println(err)
os.Exit(1)
}
data, err := yaml.Marshal(encodedData)
if err != nil {
err = fmt.Errorf("unable to marshal to yaml: %w", err)
fmt.Println(err)
os.Exit(1)
}
fmt.Println(string(data))
}
go.mod
module foo
go 1.19
require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)