@@ -329,49 +329,6 @@ func isEmptyValue(v reflect.Value) bool {
329
329
return false
330
330
}
331
331
332
- type isZeroer interface {
333
- IsZero () bool
334
- }
335
-
336
- var isZeroerType = reflect .TypeFor [isZeroer ]()
337
-
338
- func isZeroValue (v reflect.Value ) bool {
339
- // Provide a function that uses a type's IsZero method.
340
- var isZero func () bool
341
-
342
- switch {
343
- case v .Kind () == reflect .Interface && v .Type ().Implements (isZeroerType ):
344
- isZero = func () bool {
345
- // Avoid panics calling IsZero on a nil interface or
346
- // non-nil interface with nil pointer.
347
- return v .IsNil () ||
348
- (v .Elem ().Kind () == reflect .Pointer && v .Elem ().IsNil ()) ||
349
- v .Interface ().(isZeroer ).IsZero ()
350
- }
351
- case v .Kind () == reflect .Pointer && v .Type ().Implements (isZeroerType ):
352
- isZero = func () bool {
353
- // Avoid panics calling IsZero on nil pointer.
354
- return v .IsNil () || v .Interface ().(isZeroer ).IsZero ()
355
- }
356
- case v .Type ().Implements (isZeroerType ):
357
- isZero = func () bool {
358
- return v .Interface ().(isZeroer ).IsZero ()
359
- }
360
- case reflect .PointerTo (v .Type ()).Implements (isZeroerType ):
361
- isZero = func () bool {
362
- if ! v .CanAddr () {
363
- // Temporarily box v so we can take the address.
364
- v2 := reflect .New (v .Type ()).Elem ()
365
- v2 .Set (v )
366
- v = v2
367
- }
368
- return v .Addr ().Interface ().(isZeroer ).IsZero ()
369
- }
370
- }
371
-
372
- return (isZero == nil && v .IsZero () || (isZero != nil && isZero ()))
373
- }
374
-
375
332
func (e * encodeState ) reflectValue (v reflect.Value , opts encOpts ) {
376
333
valueEncoder (v )(e , v , opts )
377
334
}
@@ -756,7 +713,7 @@ FieldLoop:
756
713
}
757
714
758
715
if (f .omitEmpty && isEmptyValue (fv )) ||
759
- (f .omitZero && isZeroValue ( fv )) {
716
+ (f .omitZero && ( f . isZero == nil && fv . IsZero () || ( f . isZero != nil && f . isZero ( fv )) )) {
760
717
continue
761
718
}
762
719
e .WriteByte (next )
@@ -1104,11 +1061,18 @@ type field struct {
1104
1061
typ reflect.Type
1105
1062
omitEmpty bool
1106
1063
omitZero bool
1064
+ isZero func (reflect.Value ) bool
1107
1065
quoted bool
1108
1066
1109
1067
encoder encoderFunc
1110
1068
}
1111
1069
1070
+ type isZeroer interface {
1071
+ IsZero () bool
1072
+ }
1073
+
1074
+ var isZeroerType = reflect .TypeFor [isZeroer ]()
1075
+
1112
1076
// typeFields returns a list of fields that JSON should recognize for the given type.
1113
1077
// The algorithm is breadth-first search over the set of structs to include - the top struct
1114
1078
// and then any reachable anonymous structs.
@@ -1220,6 +1184,38 @@ func typeFields(t reflect.Type) structFields {
1220
1184
field .nameEscHTML = `"` + string (nameEscBuf ) + `":`
1221
1185
field .nameNonEsc = `"` + field .name + `":`
1222
1186
1187
+ if field .omitZero {
1188
+ t := sf .Type
1189
+ // Provide a function that uses a type's IsZero method.
1190
+ switch {
1191
+ case t .Kind () == reflect .Interface && t .Implements (isZeroerType ):
1192
+ field .isZero = func (v reflect.Value ) bool {
1193
+ // Avoid panics calling IsZero on a nil interface or
1194
+ // non-nil interface with nil pointer.
1195
+ return v .IsNil () || (v .Elem ().Kind () == reflect .Pointer && v .Elem ().IsNil ()) || v .Interface ().(isZeroer ).IsZero ()
1196
+ }
1197
+ case t .Kind () == reflect .Pointer && t .Implements (isZeroerType ):
1198
+ field .isZero = func (v reflect.Value ) bool {
1199
+ // Avoid panics calling IsZero on nil pointer.
1200
+ return v .IsNil () || v .Interface ().(isZeroer ).IsZero ()
1201
+ }
1202
+ case t .Implements (isZeroerType ):
1203
+ field .isZero = func (v reflect.Value ) bool {
1204
+ return v .Interface ().(isZeroer ).IsZero ()
1205
+ }
1206
+ case reflect .PointerTo (t ).Implements (isZeroerType ):
1207
+ field .isZero = func (v reflect.Value ) bool {
1208
+ if ! v .CanAddr () {
1209
+ // Temporarily box v so we can take the address.
1210
+ v2 := reflect .New (v .Type ()).Elem ()
1211
+ v2 .Set (v )
1212
+ v = v2
1213
+ }
1214
+ return v .Addr ().Interface ().(isZeroer ).IsZero ()
1215
+ }
1216
+ }
1217
+ }
1218
+
1223
1219
fields = append (fields , field )
1224
1220
if count [f .typ ] > 1 {
1225
1221
// If there were multiple instances, add a second,
0 commit comments