Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2 embedded structs with custom unmarshaler #473

Open
verytable opened this issue Jun 13, 2019 · 1 comment
Open

2 embedded structs with custom unmarshaler #473

verytable opened this issue Jun 13, 2019 · 1 comment

Comments

@verytable
Copy link

verytable commented Jun 13, 2019

In the following example there are 2 sets of structs (A1, B1, C1) and (A2, B2, C2).
Each Ci contains 2 embedded structs Ai and Bi (with the inline tags).
Ci are unmarshalled using the same input:

a: 3
b: 2

All structs from the first triplet use default unmarshalers and everything works as expected.

B2 from the second triplet has custom unmarshaler.
This might not be important but the unmarshaler uses type indirection (to first unmarshal into alias and then be able to validate B2 fields).

As a result of decoding data into C2 ValueA is filled with the default value 0.

There are also 2 blocks of commented unmarshalers (for structs A2 and C2) in the example program. If either of them gets uncommented then the second experiment yields the same result as the first one.

package main

import (
        "fmt"

        "gopkg.in/yaml.v2"
)

type A1 struct {
        ValueA int `yaml:"a"`
}

type B1 struct {
        ValueB int `yaml:"b"`
}

type C1 struct {
        A1 `yaml:",inline"`
        B1 `yaml:",inline"`
}

type A2 struct {
        ValueA int `yaml:"a"`
}

//func (a *A2) UnmarshalYAML(unmarshal func(interface{}) error) error {
//      type plain A2
//      if err := unmarshal((*plain)(a)); err != nil {
//              return err
//      }
//      return nil
//}

type B2 struct {
        ValueB int `yaml:"b"`
}

func (b *B2) UnmarshalYAML(unmarshal func(interface{}) error) error {
        type plain B2
        if err := unmarshal((*plain)(b)); err != nil {
                return err
        }
        return nil
}

type C2 struct {
        A2 `yaml:",inline"`
        B2 `yaml:",inline"`
}

//func (c *C2) UnmarshalYAML(unmarshal func(interface{}) error) error {
//      if err := unmarshal(&c.A2); err != nil {
//              return err
//      }
//      if err := unmarshal(&c.B2); err != nil {
//              return err
//      }
//      return nil
//}

var yamlData = []byte(`
a: 3
b: 2
`)

func main() {
        c1 := &C1{}
        if err := yaml.Unmarshal(yamlData, c1); err != nil {
                panic(err)
        }
        fmt.Printf("c1: %v\n", c1)

        c2 := &C2{}
        if err := yaml.Unmarshal(yamlData, c2); err != nil {
                panic(err)
        }
        fmt.Printf("c2: %v\n", c2)
}

Output:

c1: &{{3} {2}}
c2: &{{0} {2}}

The question is, am I doing something wrong here or this is a bug?

@kayrus
Copy link

kayrus commented Jan 13, 2021

I also faced this issue and spent an hour to debug it. Looks like it is related to #263

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants