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 基于决策树的数字信号处理,2ask 2psk 2fsk的代码,检查下报错的原因
  • ¥20 python作业求过程
  • ¥15 wincc已组态的变量过多
  • ¥60 如图:直线与椭圆X轴平行,求直线与椭圆任意一点的相切坐标计算公式
  • ¥50 如何用python使用opencv里的cv::cudacodec::VideoWriter函数对视频进行GPU硬编码
  • ¥100 c#solidworks 二次开发 工程图自动标边线法兰 等折弯尺寸怎么标
  • ¥15 halcon DrawRegion 提示错误
  • ¥15 FastAPI Uvicorn启动显示404
  • ¥15 centos7.9脚本,怎么排除特定的访问记录
  • ¥15 关于#Django#的问题:我的静态文件呢?