-
Notifications
You must be signed in to change notification settings - Fork 36
Description
For my project, I need a way to inject dependencies into an unmarshaled type or modify its behavior based on the unmarshaling context.
I'm thinking of something like this:
type Foo struct {
intValue int
}
func (f *Foo) UnmarshalYAML(ctx context.Context, value *Node) error {
var strValue string
value.Decode(&strValue)
transformer := ctx.Value("transformer").(Transformer)
f.intValue = transformer.Transform(strValue)
}
func main() {
ctx := context.WithValue(context.Background(), "transformer", NewTransformer())
var foo Foo
yaml.UnmarshalWithContext(ctx, []byte{"foo"}, &foo)
}I understand that my specific needs might go against some principles, and perhaps a different approach, such as transforming the decoded configuration into another type after unmarshaling, would be more suitable.
However, I believe that providing a context.Context to an Unmarshaler could be beneficial for other reasons as well.
My idea is to introduce a new UnmarshalerWithContext interface and an UnmarshalWithContext method. This method would forward the context.Context to the UnmarshalerWithContext interface if the target type implements it.
type UnmarshalerWithContext interface {
UnmarshalYAML(ctx context.Context, value *Node) error
}
func UnmarshalWithContext(ctx context.Context, in []byte, out any) (err error) {
...
}
I'm aware that there's an ongoing discussion about a new Unmarshaler interface in issue #56, so it might be worth considering adding context there.
Additionally, I like the idea of adding options to Unmarshal as proposed in issue #155. In that scenario, the context could be provided via an option rather than by introducing new methods.
I've already implemented this functionality for my own needs in my fork (Draft PR #186). While I'm quite happy with it as is, it would be perfect if something similar could get a chance to be introduced in a future v4 release.