mirror of
https://github.com/goccy/go-yaml.git
synced 2025-11-08 17:21:10 +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
|
## 2. Reference elements in declared in another file
|
||||||
|
|
||||||
`testdata` directory includes `anchor.yml` file
|
`testdata` directory includes `anchor.yml` file
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,13 @@ func TestDecoder(t *testing.T) {
|
||||||
"a: &a [1, 2]\nb: *a\n",
|
"a: &a [1, 2]\nb: *a\n",
|
||||||
struct{ B []int }{[]int{1, 2}},
|
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 {
|
for _, test := range tests {
|
||||||
buf := bytes.NewBufferString(test.source)
|
buf := bytes.NewBufferString(test.source)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
|
|
@ -406,3 +407,97 @@ func Example_Marshal_ImplicitAnchorAlias() {
|
||||||
// c: *a
|
// c: *a
|
||||||
// d: *b
|
// 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