2016-05-13 7 views
1

ich mit Redigo Redis Bibliothek arbeite und das Ergebnis zu json.Marshal ich versucht, aus einer sortierten Reihe bekommen, aber ich Ergebnisse zu erhalten wie folgt aus:seltsame Ergebnisse zu erzielen, wenn JSON Rangier Nahtstellenbyte Scheiben

"eyJmcm9tSWQiOjEsInRvSWQiOjUsInR5cGUiOjMsInBvc3RJZCI6MSwiY29tbWVudElkIjo0NCwiY3JlYXRlZFRpbWUiOjE0NjMxNTY0ODQsImlzVmlld2VkIjpmYWxzZSwidXNlcm5hbWUiOiJBZG1pbiIsImltYWdlIjoiaHc2ZE5EQlQtMzZ4MzYuanBnIn0=" 

Als ich sollte immer dies:

"{"fromId":5,"toId":1,"type":3,"postId":4,"commentId":49,"createdTime":1463161736,"isViewed":false,"username":"Alexander","image":"JZIfHp8i-36x36.png"}" 

ich habe eine Benachrichtigung struct

type Notification struct { 
    FromId int64 `json:"fromId"` 
    ToId int64 `json:"toId"` 
    OfType int64 `json:"type"` 

    PostId  int64 `json:"postId"` 
    CommentId int64 `json:"commentId"` 
    CreatedTime int64 `json:"createdTime"` 
    IsViewed  bool `json:"isViewed"` 
    FromUsername string `json:"username"` 
    FromImage string `json:"image"` 
} 

func New() *Notification { 
    return &Notification{ 
     CreatedTime: time.Now().Unix(), 
    } 
} 

Es verfügt über eine Methode, die eine Zeichenkette von json in eine nach Redis sortierte Menge speichert.

func (n *Notification) Create(pool *redis.Pool, multicast chan<- []byte) error { 
    var err error 
    n.FromUsername, err = validation.FilterUsername(n.FromUsername) 
    if err != nil { 
     return err 
    } 
    // We can use the same validation as for a username here. 
    n.FromImage, err = validation.FilterUsername(n.FromImage) 
    if err != nil { 
     return err 
    } 
    key := fmt.Sprintf("user:%d:notification", n.ToId) 
    b, err := json.Marshal(n) 
    if err != nil { 
     return err 
    } 
    c := pool.Get() 
    defer c.Close() 
    c.Send("ZADD", key, n.CreatedTime, string(b)) 
    // Limiting to the top ranked 50 items. 
    c.Send("ZREMRANGEBYRANK", key, 0, -50) 
    if err := c.Flush(); err != nil { 
     return err 
    } 
    multicast <- b 
    return nil 
} 

Das funktioniert alles gut. Aber dann möchte ich diese Ergebnisse abrufen und dann als ein Array von json-formatierten Strings an die Client-Seite senden. Dieselben JSON-formatierten Strings, die ich im sortierten Set speichere.

Ich mache etwas einfach so.

func ByUserId(userId int64, pool *redis.Pool) (interface{}, error) { 
    key := fmt.Sprintf("user:%d:notification", userId) 
    c := pool.Get() 
    defer c.Close() 
    c.Send("ZREVRANGE", key, 0, -1) 
    c.Flush() 
    return c.Receive() 
} 

Aber es funktioniert nicht.

Wenn ich das Ergebnis json.Marshal bekomme ich ein Array von Strings wie folgt aus:

"eyJmcm9tSWQiOjEsInRvSWQiOjUsInR5cGUiOjMsInBvc3RJZCI6MSwiY29tbWVudElkIjo0NCwiY3JlYXRlZFRpbWUiOjE0NjMxNTY0ODQsImlzVmlld2VkIjpmYWxzZSwidXNlcm5hbWUiOiJBZG1pbiIsImltYWdlIjoiaHc2ZE5EQlQtMzZ4MzYuanBnIn0=" 

Wenn ich spew.Dump() die Ergebnisse ich diese Ausgabe erhalten:

([]interface {}) (len=1 cap=1) { 
([]uint8) (len=149 cap=149) { 
    00000000 7b 22 66 72 6f 6d 49 64 22 3a 35 2c 22 74 6f 49 |{"fromId":5,"toI| 
    00000010 64 22 3a 31 2c 22 74 79 70 65 22 3a 33 2c 22 70 |d":1,"type":3,"p| 
    00000020 6f 73 74 49 64 22 3a 34 2c 22 63 6f 6d 6d 65 6e |ostId":4,"commen| 
    00000030 74 49 64 22 3a 34 39 2c 22 63 72 65 61 74 65 64 |tId":49,"created| 
    00000040 54 69 6d 65 22 3a 31 34 36 33 31 36 31 37 33 36 |Time":1463161736| 
    00000050 2c 22 69 73 56 69 65 77 65 64 22 3a 66 61 6c 73 |,"isViewed":fals| 
    00000060 65 2c 22 75 73 65 72 6e 61 6d 65 22 3a 22 53 74 |e,"username":"Al| 
    00000070 61 72 64 75 73 6b 22 2c 22 69 6d 61 67 65 22 3a |exander","image":| 
    00000080 22 4a 5a 49 66 48 70 38 69 2d 33 36 78 33 36 2e |"JZIfHp8i-36x36.| 
    00000090 70 6e 67 22 7d         |png"}| 
} 
} 

Was kann Ich mache?

EDIT:

Dies ist, was ich am Ende tat, aber es fühlt sich an wie eine Menge unnötiger Umwandlung.

func ByUserId(userId int64, pool *redis.Pool) ([]string, error) { 
    key := fmt.Sprintf("user:%d:notification", userId) 
    c := pool.Get() 
    defer c.Close() 
    c.Send("ZREVRANGE", key, 0, -1) 
    c.Flush() 
    reply, err := c.Receive() 
    if err != nil { 
     return nil, nil 
    } 
    arr, ok := reply.([]interface{}) 
    if !ok { 
     return nil, err 
    } 
    ss := []string{} 
    for _, v := range arr { 
     b, ok := v.([]byte) 
     if !ok { 
      return nil, nil 
     } 
     ss = append(ss, string(b)) 
    } 
    return ss, nil 
} 

Und auf dem Griff:

func notifications(w http.ResponseWriter, r *http.Request, _ httprouter.Params) error { 
    userId, err := user.LoggedIn(r) 
    if err != nil { 
     return unauthorized 
    } 
    jsonResp := make(map[string]interface{}) 
    jsonResp["notifications"], err = notification.ByUserId(userId, redisPool) 
    if err != nil { 
     return err 
    } 
    jsonResp["success"] = true 
    b, err := json.Marshal(jsonResp) 
    if err != nil { 
     return err 
    } 
    w.Write(b) 
    return nil 
} 
+0

ich nicht von ihnen verwenden. Wie würde ich sie in diesem Fall verwenden? – Alex

+0

Sie ordnen die von redis zurückgegebenen unverarbeiteten Bytes zu. Sie müssen nicht marshalen, was bereits json ist. – JimB

+0

Wie kann ich dann ein Array dieser JSON-Strings in der Antwort ausgeben? Ich kann nicht umhin zu denken, dass ich diese Schnittstellentypen konvertieren und ein paar Schleifen machen muss. – Alex

Antwort

0

Die Funktion ByUserId kann geschrieben werden:

func ByUserId(userId int64, pool *redis.Pool) ([]string, error) { 
    key := fmt.Sprintf("user:%d:notification", userId) 
    c := pool.Get() 
    defer c.Close() 
    return redis.Strings(c.Do("ZREVRANGE", key, 0, -1)) 
} 
+0

Danke das war sauberer. – Alex

Verwandte Themen