@@ -568,6 +568,7 @@ func appendStructFields(fields []structField, t reflect.Type, offset uintptr, se
568568 anonymous = f .Anonymous
569569 tag = false
570570 omitempty = false
571+ omitzero = false
571572 stringify = false
572573 unexported = len (f .PkgPath ) != 0
573574 )
@@ -593,6 +594,8 @@ func appendStructFields(fields []structField, t reflect.Type, offset uintptr, se
593594 switch tag {
594595 case "omitempty" :
595596 omitempty = true
597+ case "omitzero" :
598+ omitzero = true
596599 case "string" :
597600 stringify = true
598601 }
@@ -675,9 +678,11 @@ func appendStructFields(fields []structField, t reflect.Type, offset uintptr, se
675678 fields = append (fields , structField {
676679 codec : codec ,
677680 offset : offset + f .Offset ,
678- empty : emptyFuncOf (f .Type ),
681+ isEmpty : emptyFuncOf (f .Type ),
682+ isZero : zeroFuncOf (f .Type ),
679683 tag : tag ,
680684 omitempty : omitempty ,
685+ omitzero : omitzero ,
681686 name : name ,
682687 index : i << 32 ,
683688 typ : f .Type ,
@@ -895,6 +900,18 @@ func isValidTag(s string) bool {
895900 return true
896901}
897902
903+ func zeroFuncOf (t reflect.Type ) emptyFunc {
904+ if t .Implements (isZeroerType ) {
905+ return func (p unsafe.Pointer ) bool {
906+ return unsafeToAny (t , p ).(isZeroer ).IsZero ()
907+ }
908+ }
909+
910+ return func (p unsafe.Pointer ) bool {
911+ return reflectDeref (t , p ).IsZero ()
912+ }
913+ }
914+
898915func emptyFuncOf (t reflect.Type ) emptyFunc {
899916 switch t {
900917 case bytesType , rawMessageType :
@@ -908,7 +925,7 @@ func emptyFuncOf(t reflect.Type) emptyFunc {
908925 }
909926
910927 case reflect .Map :
911- return func (p unsafe.Pointer ) bool { return reflect . NewAt (t , p ). Elem ( ).Len () == 0 }
928+ return func (p unsafe.Pointer ) bool { return reflectDeref (t , p ).Len () == 0 }
912929
913930 case reflect .Slice :
914931 return func (p unsafe.Pointer ) bool { return (* slice )(p ).len == 0 }
@@ -953,6 +970,14 @@ func emptyFuncOf(t reflect.Type) emptyFunc {
953970 return func (unsafe.Pointer ) bool { return false }
954971}
955972
973+ func reflectDeref (t reflect.Type , p unsafe.Pointer ) reflect.Value {
974+ return reflect .NewAt (t , p ).Elem ()
975+ }
976+
977+ func unsafeToAny (t reflect.Type , p unsafe.Pointer ) any {
978+ return reflectDeref (t , p ).Interface ()
979+ }
980+
956981type iface struct {
957982 typ unsafe.Pointer
958983 ptr unsafe.Pointer
@@ -976,9 +1001,11 @@ type structType struct {
9761001type structField struct {
9771002 codec codec
9781003 offset uintptr
979- empty emptyFunc
1004+ isEmpty emptyFunc
1005+ isZero emptyFunc
9801006 tag bool
9811007 omitempty bool
1008+ omitzero bool
9821009 json string
9831010 html string
9841011 name string
@@ -1064,6 +1091,8 @@ type sliceHeader struct {
10641091 Cap int
10651092}
10661093
1094+ type isZeroer interface { IsZero () bool }
1095+
10671096var (
10681097 nullType = reflect .TypeOf (nil )
10691098 boolType = reflect .TypeFor [bool ]()
@@ -1111,6 +1140,7 @@ var (
11111140 jsonUnmarshalerType = reflect .TypeFor [Unmarshaler ]()
11121141 textMarshalerType = reflect .TypeFor [encoding.TextMarshaler ]()
11131142 textUnmarshalerType = reflect .TypeFor [encoding.TextUnmarshaler ]()
1143+ isZeroerType = reflect .TypeFor [isZeroer ]()
11141144
11151145 bigIntDecoder = constructJSONUnmarshalerDecodeFunc (bigIntType , false )
11161146)
0 commit comments