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

报告相同问题?

悬赏问题

  • ¥50 求解vmware的网络模式问题 别拿AI回答
  • ¥24 EFS加密后,在同一台电脑解密出错,证书界面找不到对应指纹的证书,未备份证书,求在原电脑解密的方法,可行即采纳
  • ¥15 springboot 3.0 实现Security 6.x版本集成
  • ¥15 PHP-8.1 镜像无法用dockerfile里的CMD命令启动 只能进入容器启动,如何解决?(操作系统-ubuntu)
  • ¥30 请帮我解决一下下面六个代码
  • ¥15 关于资源监视工具的e-care有知道的嘛
  • ¥35 MIMO天线稀疏阵列排布问题
  • ¥60 用visual studio编写程序,利用间接平差求解水准网
  • ¥15 Llama如何调用shell或者Python
  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?