Skip to content

Commit

Permalink
add in encoding hook
Browse files Browse the repository at this point in the history
  • Loading branch information
rfratto committed May 21, 2020
1 parent 0b1645d commit 984fc90
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
16 changes: 16 additions & 0 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type jsonNumber interface {
type encoder struct {
emitter yaml_emitter_t
event yaml_event_t
hook func(in interface{}) (ok bool, out interface{}, err error)
out []byte
flow bool
// doneInit holds whether the initial stream_start_event has been
Expand Down Expand Up @@ -100,7 +101,22 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
e.nilv()
return
}

iface := in.Interface()
if e.hook != nil {
ok, out, err := e.hook(iface)
if ok {
if err != nil {
fail(err)
}
if out == nil {
e.nilv()
return
}
iface = out
}
}

switch m := iface.(type) {
case jsonNumber:
integer, err := m.Int64()
Expand Down
32 changes: 32 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,38 @@ func (s *S) TestSortedOutput(c *C) {
}
}

type secret string

func (s secret) MarshalYAML() (interface{}, error) {
return "<secret>", nil
}

type account struct {
Username string `yaml:"username"`
Password secret `yaml:"password"`
}

func (s *S) TestEncoderHook(c *C) {
user := account{Username: "admin", Password: secret("supersecret")}

var buf bytes.Buffer
e := yaml.NewEncoder(&buf)
e.SetHook(func(in interface{}) (ok bool, out interface{}, err error) {
switch v := in.(type) {
case secret:
return true, string(v), nil
default:
return false, nil, nil
}
})

err := e.Encode(user)
c.Assert(err, IsNil)

expect := "username: admin\npassword: supersecret\n"
c.Assert(string(buf.Bytes()), Equals, expect)
}

func newTime(t time.Time) *time.Time {
return &t
}
7 changes: 7 additions & 0 deletions yaml.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,13 @@ func NewEncoder(w io.Writer) *Encoder {
}
}

// SetHook adds a marshaling hook into the Encoder. The function f will be
// called for each node to be marshalled. f must return true if the hook
// "handled" the node, in which case the output value will be used.
func (e *Encoder) SetHook(hook func(in interface{}) (ok bool, out interface{}, err error)) {
e.encoder.hook = hook
}

// Encode writes the YAML encoding of v to the stream.
// If multiple items are encoded to the stream, the
// second and subsequent document will be preceded
Expand Down

0 comments on commit 984fc90

Please sign in to comment.