mirror of
https://github.com/goccy/go-yaml.git
synced 2025-12-08 06:09:57 +00:00
feat: add global OmitEmpty encoding option (#691)
Thanks for an amazing project! Go ecosystem struggle (e.g. https://github.com/GoogleCloudPlatform/prometheus-engine/issues/1629) with 3P types that lack a good marshalling practices. Many project have config structs only designed for parsing. See https://github.com/goccy/go-yaml/issues/306 for the detailed motivation. Fixes: https://github.com/goccy/go-yaml/issues/306 The feature mechanism is simple -- we ignore struct tag setting for omitempty. We assume it's always 'omitempty' if yaml.OmitEmpty() setting is set. Signed-off-by: bwplotka <bwplotka@gmail.com>
This commit is contained in:
parent
ba0598a7f0
commit
ee37df774b
3 changed files with 34 additions and 9 deletions
|
|
@ -38,6 +38,7 @@ type Encoder struct {
|
||||||
anchorNameMap map[string]struct{}
|
anchorNameMap map[string]struct{}
|
||||||
anchorCallback func(*ast.AnchorNode, interface{}) error
|
anchorCallback func(*ast.AnchorNode, interface{}) error
|
||||||
customMarshalerMap map[reflect.Type]func(interface{}) ([]byte, error)
|
customMarshalerMap map[reflect.Type]func(interface{}) ([]byte, error)
|
||||||
|
omitEmpty bool
|
||||||
autoInt bool
|
autoInt bool
|
||||||
useLiteralStyleIfMultiline bool
|
useLiteralStyleIfMultiline bool
|
||||||
commentMap map[*Path][]*Comment
|
commentMap map[*Path][]*Comment
|
||||||
|
|
@ -824,7 +825,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
|
||||||
}
|
}
|
||||||
fieldValue := value.FieldByName(field.Name)
|
fieldValue := value.FieldByName(field.Name)
|
||||||
structField := structFieldMap[field.Name]
|
structField := structFieldMap[field.Name]
|
||||||
if structField.IsOmitEmpty && e.isZeroValue(fieldValue) {
|
if (e.omitEmpty || structField.IsOmitEmpty) && e.isZeroValue(fieldValue) {
|
||||||
// omit encoding
|
// omit encoding
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -465,7 +465,7 @@ func TestEncoder(t *testing.T) {
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Conditional flag
|
// Omitempty flag.
|
||||||
{
|
{
|
||||||
"a: 1\n",
|
"a: 1\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -482,7 +482,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{0, 0},
|
}{0, 0},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"a:\n \"y\": \"\"\n",
|
"a:\n \"y\": \"\"\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -496,7 +495,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{}},
|
}{}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"a: {}\n",
|
"a: {}\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -510,7 +508,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{}},
|
}{}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"a: {x: 1}\n",
|
"a: {x: 1}\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -518,7 +515,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{&struct{ X, y int }{1, 2}},
|
}{&struct{ X, y int }{1, 2}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"{}\n",
|
"{}\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -526,7 +522,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{nil},
|
}{nil},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"a: {x: 0}\n",
|
"a: {x: 0}\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -534,7 +529,6 @@ func TestEncoder(t *testing.T) {
|
||||||
}{&struct{ X, y int }{}},
|
}{&struct{ X, y int }{}},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"a: {x: 1}\n",
|
"a: {x: 1}\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -567,8 +561,29 @@ func TestEncoder(t *testing.T) {
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
},
|
},
|
||||||
|
// OmitEmpty global option.
|
||||||
|
{
|
||||||
|
"a: 1\n",
|
||||||
|
struct {
|
||||||
|
A int
|
||||||
|
B int `yaml:"b,omitempty"`
|
||||||
|
}{1, 0},
|
||||||
|
[]yaml.EncodeOption{
|
||||||
|
yaml.OmitEmpty(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"{}\n",
|
||||||
|
struct {
|
||||||
|
A int
|
||||||
|
B int `yaml:"b,omitempty"`
|
||||||
|
}{0, 0},
|
||||||
|
[]yaml.EncodeOption{
|
||||||
|
yaml.OmitEmpty(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
// Flow flag
|
// Flow flag.
|
||||||
{
|
{
|
||||||
"a: [1, 2]\n",
|
"a: [1, 2]\n",
|
||||||
struct {
|
struct {
|
||||||
|
|
|
||||||
|
|
@ -215,6 +215,15 @@ func AutoInt() EncodeOption {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OmitEmpty forces the encoder to assume an `omitempty` struct tag is
|
||||||
|
// set on all the fields. See `Marshal` commentary for the `omitempty` tag logic.
|
||||||
|
func OmitEmpty() EncodeOption {
|
||||||
|
return func(e *Encoder) error {
|
||||||
|
e.omitEmpty = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CommentPosition type of the position for comment.
|
// CommentPosition type of the position for comment.
|
||||||
type CommentPosition int
|
type CommentPosition int
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue