Implementing OmitEmpty flag to skip zero-value fields.

This commit is contained in:
Peter Ebden 2018-01-21 11:12:07 +00:00
parent 8991bc29aa
commit e7459a5405
3 changed files with 76 additions and 1 deletions

View File

@ -98,6 +98,10 @@ type ConfigState struct {
// be spewed to strings and sorted by those strings. This is only
// considered if SortKeys is true.
SpewKeys bool
// OmitEmpty specifies that empty struct fields should be omitted.
// Empty fields are any that have the zero value for their type.
OmitEmpty bool
}
// Config is the active configuration of the top-level functions.
@ -301,6 +305,7 @@ func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{})
// DisablePointerMethods: false
// ContinueOnMethod: false
// SortKeys: false
// OmitEmpty: false
func NewDefaultConfig() *ConfigState {
return &ConfigState{Indent: " "}
}

View File

@ -413,12 +413,16 @@ func (d *dumpState) dump(v reflect.Value) {
vt := v.Type()
numFields := v.NumField()
for i := 0; i < numFields; i++ {
vf := v.Field(i)
if d.cs.OmitEmpty && isZero(vf) {
continue
}
d.indent()
vtf := vt.Field(i)
d.w.Write([]byte(vtf.Name))
d.w.Write(colonSpaceBytes)
d.ignoreNextIndent = true
d.dump(d.unpackValue(v.Field(i)))
d.dump(d.unpackValue(vf))
if i < (numFields - 1) {
d.w.Write(commaNewlineBytes)
} else {
@ -507,3 +511,26 @@ get the formatted result as a string.
func Dump(a ...interface{}) {
fdump(&Config, os.Stdout, a...)
}
// isZero is a helper function that checks whether a reflect.Value has the zero value for its type.
func isZero(v reflect.Value) bool {
switch v.Kind() {
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
return v.Len() == 0
case reflect.Bool:
return !v.Bool()
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return v.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return v.Uint() == 0
case reflect.Float32, reflect.Float64:
return v.Float() == 0
case reflect.Interface, reflect.Ptr, reflect.Chan:
return v.IsNil()
case reflect.UnsafePointer:
return v.Pointer() == 0
case reflect.Complex64, reflect.Complex128:
return v.Complex() == 0
}
return false
}

View File

@ -1040,3 +1040,46 @@ func TestDumpSortedKeys(t *testing.T) {
}
}
func TestDumpOmitEmpty(t *testing.T) {
cfg := spew.ConfigState{OmitEmpty: true, DisablePointerAddresses: true}
type s struct {
S1 *s
S2 *s
Int int
Int8 int8
Int16 int16
Int32 int32
Int64 int64
Uint uint32
Uint8 uint8
Uint16 uint16
Uint32 uint32
Uint64 uint64
Uintptr uintptr
Float32 float32
Float64 float64
Complex64 complex64
Complex128 complex128
UnsafePtr unsafe.Pointer
Interface interface{}
Bool bool
Chan chan string
String string
Map map[string]int
Slice []string
Array [0]string
}
s1 := s{S1: &s{S2: &s{Int: 5}}}
actual := cfg.Sdump(s1)
expected := "(spew_test.s) {\n" +
"S1: (*spew_test.s)({\n" +
"S2: (*spew_test.s)({\n" +
"Int: (int) 5,\n" +
"}),\n" +
"}),\n" +
"}\n"
if actual != expected {
t.Errorf("Omit empty fields incorrect:\n %v %v", actual, expected)
}
}