Skip to content

Commit 7364aae

Browse files
authored
feat: simple string keys in ScanStruct (#692)
Support simple string keys in ScanStruct so it can be used to scan the results of FT.INFO and similar commands. Fixes: #691
1 parent a81b603 commit 7364aae

2 files changed

Lines changed: 32 additions & 3 deletions

File tree

redis/scan.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ var errScanStructValue = errors.New("redigo.ScanStruct: value must be non-nil po
477477
// ScanStruct uses exported field names to match values in the response. Use
478478
// 'redis' field tag to override the name:
479479
//
480-
// Field int `redis:"myName"`
480+
// Field int `redis:"myName"`
481481
//
482482
// Fields with the tag redis:"-" are ignored.
483483
//
@@ -513,9 +513,9 @@ func ScanStruct(src []interface{}, dest interface{}) error {
513513
continue
514514
}
515515

516-
name, ok := src[i].([]byte)
516+
name, ok := convertToBulk(src[i])
517517
if !ok {
518-
return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value", i)
518+
return fmt.Errorf("redigo.ScanStruct: key %d not a bulk string value got type: %T", i, src[i])
519519
}
520520

521521
fs := ss.fieldSpec(name)
@@ -530,6 +530,19 @@ func ScanStruct(src []interface{}, dest interface{}) error {
530530
return nil
531531
}
532532

533+
// convertToBulk converts src to a []byte if src is a string or bulk string
534+
// and returns true. Otherwise nil and false is returned.
535+
func convertToBulk(src interface{}) ([]byte, bool) {
536+
switch v := src.(type) {
537+
case []byte:
538+
return v, true
539+
case string:
540+
return []byte(v), true
541+
default:
542+
return nil, false
543+
}
544+
}
545+
533546
var (
534547
errScanSliceValue = errors.New("redigo.ScanSlice: dest must be non-nil pointer to a struct")
535548
)

redis/scan_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,22 @@ func TestScanStruct(t *testing.T) {
327327
}
328328
}
329329

330+
func TestScanStructStringKeys(t *testing.T) {
331+
reply := []interface{}{"simple", []byte("value"), "number", []byte("123")}
332+
expected := &struct {
333+
Simple string `redis:"simple"`
334+
Number int `redis:"number"`
335+
}{
336+
Simple: "value",
337+
Number: 123,
338+
}
339+
340+
value := reflect.New(reflect.ValueOf(expected).Type().Elem()).Interface()
341+
err := redis.ScanStruct(reply, value)
342+
require.NoError(t, err)
343+
require.Equal(t, expected, value)
344+
}
345+
330346
func TestBadScanStructArgs(t *testing.T) {
331347
x := []interface{}{"A", "b"}
332348
test := func(v interface{}) {

0 commit comments

Comments
 (0)