douwen1313 2016-05-13 18:22
浏览 35
已采纳

在JSON编组接口字节片时得到奇怪的结果

I am working with Redigo Redis library and trying to json.Marshal the result I get from a sorted set but I get results such as this:

"eyJmcm9tSWQiOjEsInRvSWQiOjUsInR5cGUiOjMsInBvc3RJZCI6MSwiY29tbWVudElkIjo0NCwiY3JlYXRlZFRpbWUiOjE0NjMxNTY0ODQsImlzVmlld2VkIjpmYWxzZSwidXNlcm5hbWUiOiJBZG1pbiIsImltYWdlIjoiaHc2ZE5EQlQtMzZ4MzYuanBnIn0="

When I should be getting this:

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

I have a Notification 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(),
    }
}

It has a method that saves a string of json into a Redis sorted set.

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
}

This works all good. But then I want to fetch those results and send then to the client side as an array of json formatted strings. The same json formatted strings that I save in the sorted set.

I am doing something simple like this.

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()
}

But it does not work.

When I json.Marshal the result I get an array of strings like this:

"eyJmcm9tSWQiOjEsInRvSWQiOjUsInR5cGUiOjMsInBvc3RJZCI6MSwiY29tbWVudElkIjo0NCwiY3JlYXRlZFRpbWUiOjE0NjMxNTY0ODQsImlzVmlld2VkIjpmYWxzZSwidXNlcm5hbWUiOiJBZG1pbiIsImltYWdlIjoiaHc2ZE5EQlQtMzZ4MzYuanBnIn0="

If I spew.Dump() the results I get this output:

([]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"}|
 }
}

What can I do?

EDIT:

This is what I did in the end but it feels like alot of unnecessary conversion.

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
}

And on the handle:

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
}
  • 写回答

1条回答 默认 最新

  • doujiong3146 2016-05-13 19:19
    关注

    The function ByUserId can be written as:

    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))
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?
  • ¥15 win10权限管理,限制普通用户使用删除功能
  • ¥15 minnio内存占用过大,内存没被回收(Windows环境)
  • ¥65 抖音咸鱼付款链接转码支付宝
  • ¥15 ubuntu22.04上安装ursim-3.15.8.106339遇到的问题
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案
  • ¥50 yalmip+Gurobi
  • ¥20 win10修改放大文本以及缩放与布局后蓝屏无法正常进入桌面