Support custom IsZero() methods with omitzero tag (#1020)

The omitzero tag now respects custom IsZero() methods on types,
similar to how encoding/json handles this. Previously, only
reflect.Value.IsZero() was used, which ignores user-defined
implementations.

Fixes #1003

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Pelletier
2026-01-04 13:58:47 -05:00
committed by GitHub
parent 99cd40b175
commit 692b98560b
3 changed files with 309 additions and 1 deletions
+22 -1
View File
@@ -390,7 +390,28 @@ func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
}
func shouldOmitZero(options valueOptions, v reflect.Value) bool {
return options.omitzero && v.IsZero()
if !options.omitzero {
return false
}
// Check if the type implements isZeroer interface (has a custom IsZero method).
if v.Type().Implements(isZeroerType) {
return v.Interface().(isZeroer).IsZero()
}
// Check if pointer type implements isZeroer.
if reflect.PointerTo(v.Type()).Implements(isZeroerType) {
if v.CanAddr() {
return v.Addr().Interface().(isZeroer).IsZero()
}
// Create a temporary addressable copy to call the pointer receiver method.
pv := reflect.New(v.Type())
pv.Elem().Set(v)
return pv.Interface().(isZeroer).IsZero()
}
// Fall back to reflect's IsZero for types without custom IsZero method.
return v.IsZero()
}
func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {