Skip to content

Commit ee37df7

Browse files
authored
feat: add global OmitEmpty encoding option (#691)
Thanks for an amazing project! Go ecosystem struggle (e.g. GoogleCloudPlatform/prometheus-engine#1629) with 3P types that lack a good marshalling practices. Many project have config structs only designed for parsing. See #306 for the detailed motivation. Fixes: #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 <[email protected]>
1 parent ba0598a commit ee37df7

File tree

3 files changed

+34
-9
lines changed

3 files changed

+34
-9
lines changed

encode.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type Encoder struct {
3838
anchorNameMap map[string]struct{}
3939
anchorCallback func(*ast.AnchorNode, interface{}) error
4040
customMarshalerMap map[reflect.Type]func(interface{}) ([]byte, error)
41+
omitEmpty bool
4142
autoInt bool
4243
useLiteralStyleIfMultiline bool
4344
commentMap map[*Path][]*Comment
@@ -824,7 +825,7 @@ func (e *Encoder) encodeStruct(ctx context.Context, value reflect.Value, column
824825
}
825826
fieldValue := value.FieldByName(field.Name)
826827
structField := structFieldMap[field.Name]
827-
if structField.IsOmitEmpty && e.isZeroValue(fieldValue) {
828+
if (e.omitEmpty || structField.IsOmitEmpty) && e.isZeroValue(fieldValue) {
828829
// omit encoding
829830
continue
830831
}

encode_test.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ func TestEncoder(t *testing.T) {
465465
nil,
466466
},
467467

468-
// Conditional flag
468+
// Omitempty flag.
469469
{
470470
"a: 1\n",
471471
struct {
@@ -482,7 +482,6 @@ func TestEncoder(t *testing.T) {
482482
}{0, 0},
483483
nil,
484484
},
485-
486485
{
487486
"a:\n \"y\": \"\"\n",
488487
struct {
@@ -496,7 +495,6 @@ func TestEncoder(t *testing.T) {
496495
}{}},
497496
nil,
498497
},
499-
500498
{
501499
"a: {}\n",
502500
struct {
@@ -510,31 +508,27 @@ func TestEncoder(t *testing.T) {
510508
}{}},
511509
nil,
512510
},
513-
514511
{
515512
"a: {x: 1}\n",
516513
struct {
517514
A *struct{ X, y int } `yaml:"a,omitempty,flow"`
518515
}{&struct{ X, y int }{1, 2}},
519516
nil,
520517
},
521-
522518
{
523519
"{}\n",
524520
struct {
525521
A *struct{ X, y int } `yaml:"a,omitempty,flow"`
526522
}{nil},
527523
nil,
528524
},
529-
530525
{
531526
"a: {x: 0}\n",
532527
struct {
533528
A *struct{ X, y int } `yaml:"a,omitempty,flow"`
534529
}{&struct{ X, y int }{}},
535530
nil,
536531
},
537-
538532
{
539533
"a: {x: 1}\n",
540534
struct {
@@ -567,8 +561,29 @@ func TestEncoder(t *testing.T) {
567561
},
568562
nil,
569563
},
564+
// OmitEmpty global option.
565+
{
566+
"a: 1\n",
567+
struct {
568+
A int
569+
B int `yaml:"b,omitempty"`
570+
}{1, 0},
571+
[]yaml.EncodeOption{
572+
yaml.OmitEmpty(),
573+
},
574+
},
575+
{
576+
"{}\n",
577+
struct {
578+
A int
579+
B int `yaml:"b,omitempty"`
580+
}{0, 0},
581+
[]yaml.EncodeOption{
582+
yaml.OmitEmpty(),
583+
},
584+
},
570585

571-
// Flow flag
586+
// Flow flag.
572587
{
573588
"a: [1, 2]\n",
574589
struct {

option.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,15 @@ func AutoInt() EncodeOption {
215215
}
216216
}
217217

218+
// OmitEmpty forces the encoder to assume an `omitempty` struct tag is
219+
// set on all the fields. See `Marshal` commentary for the `omitempty` tag logic.
220+
func OmitEmpty() EncodeOption {
221+
return func(e *Encoder) error {
222+
e.omitEmpty = true
223+
return nil
224+
}
225+
}
226+
218227
// CommentPosition type of the position for comment.
219228
type CommentPosition int
220229

0 commit comments

Comments
 (0)