Skip to content

Commit

Permalink
Merge pull request #356 from BurntSushi/empty
Browse files Browse the repository at this point in the history
omitempty also considers structs with all zero values "empty".
  • Loading branch information
arp242 committed Jun 7, 2022
2 parents a8d6de8 + bd45a18 commit 28ff18d
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 38 deletions.
13 changes: 13 additions & 0 deletions encode.go
Expand Up @@ -89,6 +89,17 @@ type Marshaler interface {
//
// Go maps will be sorted alphabetically by key for deterministic output.
//
// The toml struct tag can be used to provide the key name; if omitted the
// struct field name will be used. If the "omitempty" option is present the
// following value will be skipped:
//
// - arrays, slices, maps, and string with len of 0
// - struct with all zero values
// - bool false
//
// If omitzero is given all int and float types with a value of 0 will be
// skipped.
//
// Encoding Go values without a corresponding TOML representation will return an
// error. Examples of this includes maps with non-string keys, slices with nil
// elements, embedded non-struct types, and nested slices containing maps or
Expand Down Expand Up @@ -655,6 +666,8 @@ func isEmpty(rv reflect.Value) bool {
switch rv.Kind() {
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
return rv.Len() == 0
case reflect.Struct:
return reflect.Zero(rv.Type()).Interface() == rv.Interface()
case reflect.Bool:
return !rv.Bool()
}
Expand Down
67 changes: 67 additions & 0 deletions encode_test.go
Expand Up @@ -116,13 +116,78 @@ func TestEncodeArrayHashWithNormalHashOrder(t *testing.T) {
encodeExpected(t, "array hash with normal hash order", val, expected, nil)
}

func TestEncodeOmitEmptyStruct(t *testing.T) {
type (
T struct{ Int int }
Tpriv struct {
Int int
private int
}
Ttime struct {
Time time.Time
}
)

tests := []struct {
in interface{}
want string
}{
{struct {
F T `toml:"f,omitempty"`
}{}, ""},
{struct {
F T `toml:"f,omitempty"`
}{T{1}}, "[f]\n Int = 1"},

{struct {
F Tpriv `toml:"f,omitempty"`
}{}, ""},
{struct {
F Tpriv `toml:"f,omitempty"`
}{Tpriv{1, 0}}, "[f]\n Int = 1"},

// Private field being set also counts as "not empty".
{struct {
F Tpriv `toml:"f,omitempty"`
}{Tpriv{0, 1}}, "[f]\n Int = 0"},

// time.Time is common use case, so test that explicitly.
{struct {
F Ttime `toml:"t,omitempty"`
}{}, ""},
{struct {
F Ttime `toml:"t,omitempty"`
}{Ttime{time.Time{}.Add(1)}}, "[t]\n Time = 0001-01-01T00:00:00.000000001Z"},

// TODO: also test with MarshalText, MarshalTOML returning non-zero
// value.
}

for _, tt := range tests {
t.Run("", func(t *testing.T) {
buf := new(bytes.Buffer)

err := NewEncoder(buf).Encode(tt.in)
if err != nil {
t.Fatal(err)
}

have := strings.TrimSpace(buf.String())
if have != tt.want {
t.Errorf("\nhave:\n%s\nwant:\n%s", have, tt.want)
}
})
}
}

func TestEncodeWithOmitEmpty(t *testing.T) {
type simple struct {
Bool bool `toml:"bool,omitempty"`
String string `toml:"string,omitempty"`
Array [0]byte `toml:"array,omitempty"`
Slice []int `toml:"slice,omitempty"`
Map map[string]string `toml:"map,omitempty"`
Time time.Time `toml:"time,omitempty"`
}

var v simple
Expand All @@ -132,10 +197,12 @@ func TestEncodeWithOmitEmpty(t *testing.T) {
String: " ",
Slice: []int{2, 3, 4},
Map: map[string]string{"foo": "bar"},
Time: time.Date(1985, 6, 18, 15, 16, 17, 0, time.UTC),
}
expected := `bool = true
string = " "
slice = [2, 3, 4]
time = 1985-06-18T15:16:17Z
[map]
foo = "bar"
Expand Down
3 changes: 3 additions & 0 deletions internal/toml-test/json.go
@@ -1,3 +1,6 @@
//go:build go1.16
// +build go1.16

package tomltest

import (
Expand Down
38 changes: 0 additions & 38 deletions internal/toml-test/runner_test.go

This file was deleted.

3 changes: 3 additions & 0 deletions internal/toml-test/toml.go
@@ -1,3 +1,6 @@
//go:build go1.16
// +build go1.16

package tomltest

import (
Expand Down
3 changes: 3 additions & 0 deletions internal/toml-test/version.go
@@ -1,3 +1,6 @@
//go:build go1.16
// +build go1.16

package tomltest

type versionSpec struct {
Expand Down

0 comments on commit 28ff18d

Please sign in to comment.