Bladeren bron

Added support for "omitempty" tag

Dmytro Shteflyuk 10 jaren geleden
bovenliggende
commit
7a0cba7bcb
2 gewijzigde bestanden met toevoegingen van 46 en 11 verwijderingen
  1. 25 5
      redis/scan.go
  2. 21 6
      redis/scan_test.go

+ 25 - 5
redis/scan.go

@@ -234,9 +234,9 @@ func Scan(src []interface{}, dest ...interface{}) ([]interface{}, error) {
 }
 
 type fieldSpec struct {
-	name  string
-	index []int
-	//omitEmpty bool
+	name      string
+	index     []int
+	omitEmpty bool
 }
 
 type structSpec struct {
@@ -273,8 +273,8 @@ func compileStructSpec(t reflect.Type, depth map[string]int, index []int, ss *st
 				}
 				for _, s := range p[1:] {
 					switch s {
-					//case "omitempty":
-					//  fs.omitempty = true
+					case "omitempty":
+						fs.omitEmpty = true
 					default:
 						panic(fmt.Errorf("redigo: unknown field tag %s for type %s", s, t.Name()))
 					}
@@ -522,6 +522,26 @@ func flattenStruct(args Args, v reflect.Value) Args {
 	ss := structSpecForType(v.Type())
 	for _, fs := range ss.l {
 		fv := v.FieldByIndex(fs.index)
+		if fs.omitEmpty {
+			var empty = false
+			switch fv.Kind() {
+			case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+				empty = fv.Len() == 0
+			case reflect.Bool:
+				empty = !fv.Bool()
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				empty = fv.Int() == 0
+			case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+				empty = fv.Uint() == 0
+			case reflect.Float32, reflect.Float64:
+				empty = fv.Float() == 0
+			case reflect.Interface, reflect.Ptr:
+				empty = fv.IsNil()
+			}
+			if empty {
+				continue
+			}
+		}
 		args = append(args, fs.name, fv.Interface())
 	}
 	return args

+ 21 - 6
redis/scan_test.go

@@ -339,16 +339,17 @@ var argsTests = []struct {
 }{
 	{"struct ptr",
 		redis.Args{}.AddFlat(&struct {
-			I  int    `redis:"i"`
-			U  uint   `redis:"u"`
-			S  string `redis:"s"`
-			P  []byte `redis:"p"`
+			I  int               `redis:"i"`
+			U  uint              `redis:"u"`
+			S  string            `redis:"s"`
+			P  []byte            `redis:"p"`
+			M  map[string]string `redis:"m"`
 			Bt bool
 			Bf bool
 		}{
-			-1234, 5678, "hello", []byte("world"), true, false,
+			-1234, 5678, "hello", []byte("world"), map[string]string{"hello": "world"}, true, false,
 		}),
-		redis.Args{"i", int(-1234), "u", uint(5678), "s", "hello", "p", []byte("world"), "Bt", true, "Bf", false},
+		redis.Args{"i", int(-1234), "u", uint(5678), "s", "hello", "p", []byte("world"), "m", map[string]string{"hello": "world"}, "Bt", true, "Bf", false},
 	},
 	{"struct",
 		redis.Args{}.AddFlat(struct{ I int }{123}),
@@ -358,6 +359,20 @@ var argsTests = []struct {
 		redis.Args{}.Add(1).AddFlat([]string{"a", "b", "c"}).Add(2),
 		redis.Args{1, "a", "b", "c", 2},
 	},
+	{"struct omitempty",
+		redis.Args{}.AddFlat(&struct {
+			I  int               `redis:"i,omitempty"`
+			U  uint              `redis:"u,omitempty"`
+			S  string            `redis:"s,omitempty"`
+			P  []byte            `redis:"p,omitempty"`
+			M  map[string]string `redis:"m,omitempty"`
+			Bt bool              `redis:"Bt,omitempty"`
+			Bf bool              `redis:"Bf,omitempty"`
+		}{
+			0, 0, "", []byte{}, map[string]string{}, true, false,
+		}),
+		redis.Args{"Bt", true},
+	},
 }
 
 func TestArgs(t *testing.T) {