Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions marshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
//
// The "omitempty" option prevents empty values or groups from being emitted.
//
// The "omitzero" option prevents zero values or groups from being emitted.
//
// The "commented" option prefixes the value and all its children with a comment
// symbol.
//
Expand Down Expand Up @@ -196,6 +198,7 @@ func (enc *Encoder) Encode(v interface{}) error {
type valueOptions struct {
multiline bool
omitempty bool
omitzero bool
commented bool
comment string
}
Expand Down Expand Up @@ -384,6 +387,10 @@ func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
return options.omitempty && isEmptyValue(v)
}

func shouldOmitZero(options valueOptions, v reflect.Value) bool {
return options.omitzero && v.IsZero()
}

func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
var err error

Expand Down Expand Up @@ -774,6 +781,7 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
options := valueOptions{
multiline: opts.multiline,
omitempty: opts.omitempty,
omitzero: opts.omitzero,
commented: opts.commented,
comment: fieldType.Tag.Get("comment"),
}
Expand Down Expand Up @@ -834,6 +842,7 @@ type tagOptions struct {
multiline bool
inline bool
omitempty bool
omitzero bool
commented bool
}

Expand Down Expand Up @@ -862,6 +871,8 @@ func parseTag(tag string) (string, tagOptions) {
opts.inline = true
case "omitempty":
opts.omitempty = true
case "omitzero":
opts.omitzero = true
case "commented":
opts.commented = true
}
Expand Down Expand Up @@ -896,6 +907,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
if shouldOmitEmpty(kv.Options, kv.Value) {
continue
}
if shouldOmitZero(kv.Options, kv.Value) {
continue
}
hasNonEmptyKV = true

ctx.setKey(kv.Key)
Expand All @@ -915,6 +929,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
if shouldOmitEmpty(table.Options, table.Value) {
continue
}
if shouldOmitZero(table.Options, table.Value) {
continue
}
if first {
first = false
if hasNonEmptyKV {
Expand Down Expand Up @@ -949,6 +966,9 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
if shouldOmitEmpty(kv.Options, kv.Value) {
continue
}
if shouldOmitZero(kv.Options, kv.Value) {
continue
}

if first {
first = false
Expand Down
67 changes: 66 additions & 1 deletion marshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"math"
"math/big"
"net/netip"
"reflect"
"strings"
"testing"
Expand Down Expand Up @@ -1117,14 +1118,78 @@ func TestEncoderOmitempty(t *testing.T) {
Ptr *string `toml:",omitempty,multiline"`
Iface interface{} `toml:",omitempty,multiline"`
Struct struct{} `toml:",omitempty,multiline"`
Inline struct {
String string `toml:",omitempty,multiline"`
} `toml:",inline"`
}

d := doc{}

b, err := toml.Marshal(d)
assert.NoError(t, err)

expected := ``
expected := `Inline = {}
`

assert.Equal(t, expected, string(b))
}

func TestEncoderOmitzero(t *testing.T) {
type doc struct {
String string `toml:",omitzero,multiline"`
Bool bool `toml:",omitzero,multiline"`
Int int `toml:",omitzero,multiline"`
Int8 int8 `toml:",omitzero,multiline"`
Int16 int16 `toml:",omitzero,multiline"`
Int32 int32 `toml:",omitzero,multiline"`
Int64 int64 `toml:",omitzero,multiline"`
Uint uint `toml:",omitzero,multiline"`
Uint8 uint8 `toml:",omitzero,multiline"`
Uint16 uint16 `toml:",omitzero,multiline"`
Uint32 uint32 `toml:",omitzero,multiline"`
Uint64 uint64 `toml:",omitzero,multiline"`
Float32 float32 `toml:",omitzero,multiline"`
Float64 float64 `toml:",omitzero,multiline"`
MapNil map[string]string `toml:",omitzero,multiline"`
Slice []string `toml:",omitzero,multiline"`
Ptr *string `toml:",omitzero,multiline"`
Iface interface{} `toml:",omitzero,multiline"`
Struct struct{} `toml:",omitzero,multiline"`
Time time.Time `toml:",omitzero,multiline"`
IP netip.Addr `toml:",omitzero,multiline"`
Inline struct {
String string `toml:",omitzero,multiline"`
} `toml:",inline"`
}

d := doc{}

b, err := toml.Marshal(d)
assert.NoError(t, err)

expected := `Inline = {}
`

assert.Equal(t, expected, string(b))
}

func TestEncoderOmitzeroOpaqueStruct(t *testing.T) {
type doc struct {
Time time.Time `toml:",omitzero"`
IP netip.Addr `toml:",omitzero"`
}

d := doc{
Time: time.Date(2001, 2, 3, 4, 5, 6, 7, time.UTC),
IP: netip.MustParseAddr("192.168.178.35"),
}

b, err := toml.Marshal(d)
assert.NoError(t, err)

expected := `Time = 2001-02-03T04:05:06.000000007Z
IP = '192.168.178.35'
`

assert.Equal(t, expected, string(b))
}
Expand Down
Loading