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

req: better docs around InterfaceMarshaler/InterfaceUnmarshaler #446

Open
nergdron opened this issue Apr 22, 2024 · 0 comments
Open

req: better docs around InterfaceMarshaler/InterfaceUnmarshaler #446

nergdron opened this issue Apr 22, 2024 · 0 comments

Comments

@nergdron
Copy link

nergdron commented Apr 22, 2024

Is your feature request related to a problem? Please describe.
I'm trying to wrap Masterminds/semver's Version type with a custom (un)marshaler. However, when I write an UnmarshalYAML for it, I get an error I don't understand trying to unmarshal the simple string field in my YAML file.

Describe the solution you'd like
It'd be great to have examples of unmarshaling custom types from basic, complex, and nested YAML fields in the docs, to make it clear how this is supposed to function. the Canonical YAML lib has already moved away from this interface, and instead provides direct *Node access when parsing, so it's been hard finding any examples of what I'm trying to do (parse a string field to a more nuanced type).

Describe alternatives you've considered
I could probably implement this by implementing the BytesUnmarshaler interface instead, but the docs indicate that InterfaceUnmarshaler is more efficient, and my use case involves rapidly generating a lot of YAML from a constantly changing dataset, so I'd really like to figure out how to implement this correctly.

Additional context
Here's my current implementation:

type Data struct {
  Version
}

type Version semver.Version

// UnmarshalYAML is a custom unmarshaler for go-yaml.
func (V *Version) UnmarshalYAML(unmarshal func(interface{}) error) (err error) {
	var raw string
	if err = unmarshal(&raw); err != nil {
		return err
	}

	v, err := semver.NewVersion(raw)
	if err != nil {
		return err
	}
	*V = (Version)(*v)

	return nil
}

// MarshalYAML is a custom marshaler for go-yaml.
func (V *Version) MarshalYAML() (i interface{}, err error) {
	s := (*semver.Version)(V).String()
	return s, nil
}

here's my test YAML file:

version: 0.0.1

when trying to unmarshal the above YAML into a Data struct, I get the following error:

=== RUN   TestValidation
    schema_v0_test.go:35: [1:8] cannot unmarshal map[string]interface {} into Go value of type string
            >  1 | version: "0.0.1"
                          ^
    schema_v0_test.go:27: 0.0.0
        
--- FAIL: TestValidation (0.00s)
FAIL
exit status 1

I really don't understand why it thinks this field is a map, when it's just a simple string field. and when I tested unmarshaling it to a map[string]string, the library seems to unmarshal the whole document into a map, rather than the specific field I'm trying to parse. so I clearly don't understand how this is supposed to work. 😅

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

No branches or pull requests

1 participant