Skip to content
This repository was archived by the owner on Apr 1, 2025. It is now read-only.

Commit f3e79e4

Browse files
committed
Make yaml.Node.Decode customizable with decoder options
1 parent f6f7691 commit f3e79e4

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

decode_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,6 +1703,35 @@ func (s *S) TestUnmarshalKnownFields(c *C) {
17031703
}
17041704
}
17051705

1706+
type decoderOptionsTest struct {
1707+
Foo int
1708+
Bar string
1709+
}
1710+
1711+
// contrived example only for the sake of showcasing the
1712+
// custom unmarshalling logic
1713+
func (i *decoderOptionsTest) UnmarshalYAML(data *yaml.Node) error {
1714+
repr := struct {
1715+
Foo int
1716+
Bar string
1717+
}{}
1718+
if err := data.Decode(&repr, yaml.NodeDecoderOptions.KnownFields); err != nil {
1719+
return err
1720+
}
1721+
i.Foo = repr.Foo
1722+
i.Bar = repr.Bar
1723+
return nil
1724+
}
1725+
1726+
func (s *S) TestDecoderOptions(c *C) {
1727+
testData := "foo: 42\nbar: \"bar\"\nsome_random_field: 666"
1728+
out := decoderOptionsTest{}
1729+
dec := yaml.NewDecoder(bytes.NewBuffer([]byte(testData)))
1730+
dec.KnownFields(true)
1731+
err := dec.Decode(&out)
1732+
c.Assert(err, ErrorMatches, "yaml: unmarshal errors:\n line 3: field some_random_field not found in type struct { Foo int; Bar string }")
1733+
}
1734+
17061735
type textUnmarshaler struct {
17071736
S string
17081737
}

yaml.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,12 +135,29 @@ func (dec *Decoder) Decode(v interface{}) (err error) {
135135
return nil
136136
}
137137

138+
// NodeDecoderOption allows configuring decoder with custom options.
139+
//
140+
// It is especially useful when implementing UnmarshalYAML for custom data types.
141+
type NodeDecoderOption func(d *decoder)
142+
143+
// NodeDecoderOptions stores all currently available decoder configuration options.
144+
var NodeDecoderOptions = struct {
145+
KnownFields NodeDecoderOption
146+
}{
147+
KnownFields: func(d *decoder) {
148+
d.knownFields = true
149+
},
150+
}
151+
138152
// Decode decodes the node and stores its data into the value pointed to by v.
139153
//
140154
// See the documentation for Unmarshal for details about the
141155
// conversion of YAML into a Go value.
142-
func (n *Node) Decode(v interface{}) (err error) {
156+
func (n *Node) Decode(v interface{}, nodeDecoderOptions ...NodeDecoderOption) (err error) {
143157
d := newDecoder()
158+
for _, opt := range nodeDecoderOptions {
159+
opt(d)
160+
}
144161
defer handleErr(&err)
145162
out := reflect.ValueOf(v)
146163
if out.Kind() == reflect.Ptr && !out.IsNil() {

0 commit comments

Comments
 (0)