Skip to content

Commit c57d0d5

Browse files
authored
Add omitzero tag support (#998)
1 parent 644602b commit c57d0d5

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

marshaler.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder {
161161
//
162162
// The "omitempty" option prevents empty values or groups from being emitted.
163163
//
164+
// The "omitzero" option prevents zero values or groups from being emitted.
165+
//
164166
// The "commented" option prefixes the value and all its children with a comment
165167
// symbol.
166168
//
@@ -196,6 +198,7 @@ func (enc *Encoder) Encode(v interface{}) error {
196198
type valueOptions struct {
197199
multiline bool
198200
omitempty bool
201+
omitzero bool
199202
commented bool
200203
comment string
201204
}
@@ -384,6 +387,10 @@ func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
384387
return options.omitempty && isEmptyValue(v)
385388
}
386389

390+
func shouldOmitZero(options valueOptions, v reflect.Value) bool {
391+
return options.omitzero && v.IsZero()
392+
}
393+
387394
func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
388395
var err error
389396

@@ -774,6 +781,7 @@ func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
774781
options := valueOptions{
775782
multiline: opts.multiline,
776783
omitempty: opts.omitempty,
784+
omitzero: opts.omitzero,
777785
commented: opts.commented,
778786
comment: fieldType.Tag.Get("comment"),
779787
}
@@ -834,6 +842,7 @@ type tagOptions struct {
834842
multiline bool
835843
inline bool
836844
omitempty bool
845+
omitzero bool
837846
commented bool
838847
}
839848

@@ -862,6 +871,8 @@ func parseTag(tag string) (string, tagOptions) {
862871
opts.inline = true
863872
case "omitempty":
864873
opts.omitempty = true
874+
case "omitzero":
875+
opts.omitzero = true
865876
case "commented":
866877
opts.commented = true
867878
}
@@ -896,6 +907,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
896907
if shouldOmitEmpty(kv.Options, kv.Value) {
897908
continue
898909
}
910+
if shouldOmitZero(kv.Options, kv.Value) {
911+
continue
912+
}
899913
hasNonEmptyKV = true
900914

901915
ctx.setKey(kv.Key)
@@ -915,6 +929,9 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
915929
if shouldOmitEmpty(table.Options, table.Value) {
916930
continue
917931
}
932+
if shouldOmitZero(table.Options, table.Value) {
933+
continue
934+
}
918935
if first {
919936
first = false
920937
if hasNonEmptyKV {
@@ -949,6 +966,9 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
949966
if shouldOmitEmpty(kv.Options, kv.Value) {
950967
continue
951968
}
969+
if shouldOmitZero(kv.Options, kv.Value) {
970+
continue
971+
}
952972

953973
if first {
954974
first = false

marshaler_test.go

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"math"
88
"math/big"
9+
"net/netip"
910
"reflect"
1011
"strings"
1112
"testing"
@@ -1117,14 +1118,78 @@ func TestEncoderOmitempty(t *testing.T) {
11171118
Ptr *string `toml:",omitempty,multiline"`
11181119
Iface interface{} `toml:",omitempty,multiline"`
11191120
Struct struct{} `toml:",omitempty,multiline"`
1121+
Inline struct {
1122+
String string `toml:",omitempty,multiline"`
1123+
} `toml:",inline"`
11201124
}
11211125

11221126
d := doc{}
11231127

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

1127-
expected := ``
1131+
expected := `Inline = {}
1132+
`
1133+
1134+
assert.Equal(t, expected, string(b))
1135+
}
1136+
1137+
func TestEncoderOmitzero(t *testing.T) {
1138+
type doc struct {
1139+
String string `toml:",omitzero,multiline"`
1140+
Bool bool `toml:",omitzero,multiline"`
1141+
Int int `toml:",omitzero,multiline"`
1142+
Int8 int8 `toml:",omitzero,multiline"`
1143+
Int16 int16 `toml:",omitzero,multiline"`
1144+
Int32 int32 `toml:",omitzero,multiline"`
1145+
Int64 int64 `toml:",omitzero,multiline"`
1146+
Uint uint `toml:",omitzero,multiline"`
1147+
Uint8 uint8 `toml:",omitzero,multiline"`
1148+
Uint16 uint16 `toml:",omitzero,multiline"`
1149+
Uint32 uint32 `toml:",omitzero,multiline"`
1150+
Uint64 uint64 `toml:",omitzero,multiline"`
1151+
Float32 float32 `toml:",omitzero,multiline"`
1152+
Float64 float64 `toml:",omitzero,multiline"`
1153+
MapNil map[string]string `toml:",omitzero,multiline"`
1154+
Slice []string `toml:",omitzero,multiline"`
1155+
Ptr *string `toml:",omitzero,multiline"`
1156+
Iface interface{} `toml:",omitzero,multiline"`
1157+
Struct struct{} `toml:",omitzero,multiline"`
1158+
Time time.Time `toml:",omitzero,multiline"`
1159+
IP netip.Addr `toml:",omitzero,multiline"`
1160+
Inline struct {
1161+
String string `toml:",omitzero,multiline"`
1162+
} `toml:",inline"`
1163+
}
1164+
1165+
d := doc{}
1166+
1167+
b, err := toml.Marshal(d)
1168+
assert.NoError(t, err)
1169+
1170+
expected := `Inline = {}
1171+
`
1172+
1173+
assert.Equal(t, expected, string(b))
1174+
}
1175+
1176+
func TestEncoderOmitzeroOpaqueStruct(t *testing.T) {
1177+
type doc struct {
1178+
Time time.Time `toml:",omitzero"`
1179+
IP netip.Addr `toml:",omitzero"`
1180+
}
1181+
1182+
d := doc{
1183+
Time: time.Date(2001, 2, 3, 4, 5, 6, 7, time.UTC),
1184+
IP: netip.MustParseAddr("192.168.178.35"),
1185+
}
1186+
1187+
b, err := toml.Marshal(d)
1188+
assert.NoError(t, err)
1189+
1190+
expected := `Time = 2001-02-03T04:05:06.000000007Z
1191+
IP = '192.168.178.35'
1192+
`
11281193

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

0 commit comments

Comments
 (0)