feat: honour the omitzero and omitempty tag options on encode
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -189,6 +189,9 @@ func buildStructDoc(v reflect.Value, doc *tomlDoc, ctx string) error {
|
||||
if name == "-" {
|
||||
continue
|
||||
}
|
||||
if fieldOmitted(f, v.Field(i)) {
|
||||
continue
|
||||
}
|
||||
if err := addField(doc, name, v.Field(i), ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -196,6 +199,49 @@ func buildStructDoc(v reflect.Value, doc *tomlDoc, ctx string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// isZeroer mirrors encoding/json's omitzero: a type that knows its own zero
|
||||
// state decides through that method before reflection is consulted.
|
||||
type isZeroer interface{ IsZero() bool }
|
||||
|
||||
// fieldOmitted reports whether the field's tag options drop it from the
|
||||
// output: omitzero skips the zero value of the field's type, omitempty skips
|
||||
// an empty collection (slice, array, or map). The decoder ignores both
|
||||
// options; they shape emission only.
|
||||
func fieldOmitted(f reflect.StructField, v reflect.Value) bool {
|
||||
tag, ok := f.Tag.Lookup("toml")
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, opts, _ := strings.Cut(tag, ",")
|
||||
for opts != "" {
|
||||
var opt string
|
||||
opt, opts, _ = strings.Cut(opts, ",")
|
||||
switch opt {
|
||||
case "omitzero":
|
||||
if isZeroValue(v) {
|
||||
return true
|
||||
}
|
||||
case "omitempty":
|
||||
switch v.Kind() {
|
||||
case reflect.Slice, reflect.Array, reflect.Map:
|
||||
if v.Len() == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isZeroValue(v reflect.Value) bool {
|
||||
if v.CanInterface() {
|
||||
if z, ok := v.Interface().(isZeroer); ok {
|
||||
return z.IsZero()
|
||||
}
|
||||
}
|
||||
return v.IsZero()
|
||||
}
|
||||
|
||||
// fieldName returns the TOML key for a struct field, honouring the `toml`
|
||||
// tag (name or `-`) and falling back to a lower-cased field name.
|
||||
func fieldName(f reflect.StructField) string {
|
||||
|
||||
Reference in New Issue
Block a user