1

我有一个由浏览器发布的 json。这是一个哈希

var id int64 = 123 

比如说,三个像这样的字段:

myJson := `{ 
    "a":"{'x1':'apple','x2':'orange'}", 
    "b":"{'y1':345678,'y2':32456}", 
    "c":"['alpha@example1.com', 'beta@example2.com']"}`

然后使用redigo命令将其存储在 Redis 中:

HMSET id:123 a "{'x1':'apple','x2':'orange'}" b "{'y1':345678,'y2':32456}" c "['alpha@example1.com', 'beta@example2.com']"

现在,我想在 Go 中使用这样的模型

type Model struct {
    A string `json:"a"`
    B string `json:"b"`
    C string `json:"c"` // Unknown length of map at runtime
}

1.我打电话给Redis

v, _ := redis.Values(c.Do("HGETALL", "id:123"))

我通过 redis-cli 看到正确存储的值,但是将v回复转换为Model结构不起作用:

var model Model
if err := redis.ScanStruct(v, &model); err != nil {
    panic(err)
}
fmt.Printf("c %#v\n", model.C) => empty []

我想访问单独的 k:v 对,例如:

B.y2 = 32456
C[0] = "alpha@example1.com"

2.我还想将 json.Marshal myJson作为 {a}、{a,b}、{a,c}、{a,b,c} 等的组合返回浏览器。我不确定如何将各种 a、b、c 字段组合组合成一个进行编组。

任何帮助,将不胜感激。

4

3 回答 3

2

首先,您应该使用标签redis而不是json标签来标记您的字段名称,这就是 redigo 用于 ScanStruct() 的内容。例如

type Model struct {
    A string `redis:"a"`
    B string `redis:"b"`
    C string `redis:"c"` // Unknown length of map at runtime
}

其次,您的成员是字符串,因此您不能让单个成员访问他们的内容,而且我认为您不能使用 redigo 将其自动化。

您可以,因为解决方法有一些扩展字符串的类型,并且有一个访问方法,可以将 json 延迟解析为底层字典,然后返回值。像这样的东西(没有测试就写,只是一般的想法,我不确定它会起作用,但值得一试):

type MyString string

func (s MyString)Get(key string) (interface{}, error) {
   var m map[string]interface{}

   if err := json.Unmarshal([]byte(s), &m); err != nil {
       return nil, err
   } 

   return m[key], nil

}

它也不是很有效,因为它每次都会再次解析 json。就我个人而言,我会将整个模型的东西包装在一个结构中,该结构在从 redigo 反序列化的同时执行场景背后的所有逻辑。

于 2015-05-10T10:47:09.790 回答
1

查看 RedisLabs 的ReJSON模块。

我在这里为它创建了一个与 Redigo一起使用的简单 go-client 。

type Model struct {
    A string `redis:"a" json:"a"`
    B string `redis:"b" json:"b"`
    C string `redis:"c" json:"c"`
}

要读回它,请使用JSON.GET命令,

v, err := redis.Bytes(rejson.JSONGet(conn, "id:123", ""))
if err != nil {
    return
}

m := new(Model)
err = json.Unmarshal(v, m)
if err != nil {
    return
}
于 2018-05-18T13:19:25.733 回答
0
type Model struct {
    A string `redis:"a" json:"a"`
    B string `redis:"b" json:"b"`
    C string `redis:"c" json:"c"`
}

您可以同时使用redis标签和json标签。
ScanStruct 应该可以正常工作,它使用redis标签。

m := Model
v, err := redis.Values(c.Do("HGETALL", key))
err = redis.ScanStruct(v, &m)
于 2017-03-03T13:20:48.267 回答