mirror of
https://github.com/goccy/go-yaml.git
synced 2025-11-01 22:01:05 +00:00
documentation about he (Un)?Marshalers
This commit is contained in:
parent
01e45ca83c
commit
40ece17985
3 changed files with 111 additions and 0 deletions
|
|
@ -63,6 +63,15 @@ if err := yaml.Unmarshal([]byte(yml), &v); err != nil {
|
|||
}
|
||||
```
|
||||
|
||||
For custom marshal/unmarshaling, implement one of Bytes or Interface Marshaler/Unmarshaler. The difference is that while BytesMarshaler/BytesUnmarshaler behave like `encoding.json`, InterfaceMarshaler/InterfaceUnmarshaler behave like `gopkg.in/yaml.v2`.
|
||||
|
||||
Semantically both are the same, but they differ in performance. Because indentation matter in YAML, you cannot simply accept a valid YAML fragment from a Marshaler, and expect it to work when it is attached to the parent container's serialized form. Therefore when we receive use the BytesMarshaler, which returns []byte, we must decode it once to figure out how to make it work in the given context. If you use the InterfaceMarshaler, we can skip the decoding.
|
||||
|
||||
If you are repeatedly marshaling complex objects, the latter is always better
|
||||
performance wise. But if you are, for example, just providing a choice between
|
||||
a config file format that is read only once, the former is probably easier to
|
||||
code.
|
||||
|
||||
## 2. Reference elements in declared in another file
|
||||
|
||||
`testdata` directory includes `anchor.yml` file
|
||||
|
|
|
|||
|
|
@ -279,6 +279,13 @@ func TestDecoder(t *testing.T) {
|
|||
"a: &a [1, 2]\nb: *a\n",
|
||||
struct{ B []int }{[]int{1, 2}},
|
||||
},
|
||||
{
|
||||
"tags:\n- hello-world\na: foo",
|
||||
struct {
|
||||
Tags []string
|
||||
A string
|
||||
}{Tags: []string{"hello-world"}, A: "foo"},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := bytes.NewBufferString(test.source)
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/goccy/go-yaml"
|
||||
|
|
@ -406,3 +407,97 @@ func Example_Marshal_ImplicitAnchorAlias() {
|
|||
// c: *a
|
||||
// d: *b
|
||||
}
|
||||
|
||||
type tMarshal []string
|
||||
|
||||
func (t *tMarshal) MarshalYAML() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("tags:\n")
|
||||
for i, v := range *t {
|
||||
if i == 0 {
|
||||
fmt.Fprintf(&buf, "- %s\n", v)
|
||||
} else {
|
||||
fmt.Fprintf(&buf, " %s\n", v)
|
||||
}
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
func Test_Marshaler(t *testing.T) {
|
||||
const expected = `- hello-world
|
||||
`
|
||||
|
||||
// sanity check
|
||||
var l []string
|
||||
if err := yaml.Unmarshal([]byte(expected), &l); err != nil {
|
||||
t.Fatalf("failed to parse string: %s", err)
|
||||
}
|
||||
|
||||
buf, err := yaml.Marshal(tMarshal{"hello-world"})
|
||||
if err != nil {
|
||||
t.Fatalf("failed to marshal: %s", err)
|
||||
}
|
||||
|
||||
if string(buf) != expected {
|
||||
t.Fatalf("expected '%s', got '%s'", expected, buf)
|
||||
}
|
||||
|
||||
t.Logf("%s", buf)
|
||||
}
|
||||
|
||||
type SlowMarshaler struct {
|
||||
A string
|
||||
B int
|
||||
}
|
||||
type FastMarshaler struct {
|
||||
A string
|
||||
B int
|
||||
}
|
||||
|
||||
func (v SlowMarshaler) MarshalYAML() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString("tags:\n")
|
||||
buf.WriteString("- slow-marshaler\n")
|
||||
buf.WriteString("a: " + v.A + "\n")
|
||||
buf.WriteString("b: " + strconv.FormatInt(int64(v.B), 10) + "\n")
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
func (v FastMarshaler) MarshalYAML() (interface{}, error) {
|
||||
return yaml.MapSlice{
|
||||
{"tags", []string{"fast-marshaler"}},
|
||||
{"a", v.A},
|
||||
{"b", v.B},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Example_MarshalYAML() {
|
||||
var slow SlowMarshaler
|
||||
slow.A = "Hello slow poke"
|
||||
slow.B = 100
|
||||
buf, err := yaml.Marshal(slow)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println(string(buf))
|
||||
|
||||
var fast FastMarshaler
|
||||
fast.A = "Hello speed demon"
|
||||
fast.B = 100
|
||||
buf, err = yaml.Marshal(fast)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
fmt.Println(string(buf))
|
||||
// OUTPUT:
|
||||
// tags:
|
||||
// - slow-marshaler
|
||||
// a: Hello slow poke
|
||||
// b: 100
|
||||
//
|
||||
// tags:
|
||||
// - fast-marshaler
|
||||
// a: Hello speed demon
|
||||
// b: 100
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue