将 JSON 转换为 Go interface{}

3
我有一个包含类型为 interface{} 的字段的结构体。在使用 memcached(https://github.com/bradfitz/gomemcache)进行缓存时,该结构体被编组成 JSON,然后在从缓存中检索时重新解组回结构体。结果,interface{} 字段不可避免地指向类型为 map[string]interface{} 的对象(即,只能将 interface{} 字段断言为 map[string]interface{}),由于编组和解组过程未保留类型信息。是否有办法在编组过程中保存此信息,以便可以正确地解组?还是我必须使用其他编解码器等工具?
type A struct {
    value interface{}
}

type B struct {
    name string
    id string
}

func main() {
    a := A{value: B{name: "hi", id: "12345"}}
    cache.Set("a", a) // Marshals 'a' into JSON and stores in cache
    result = cache.Get("a") // Retrieves 'a' from cache and unmarshals
    fmt.Printf("%s", result.value.(B).name) // Generates error saying that 
        // map[string]interface{} cannot be type asserted as a 'B' struct
    fmt.Printf("%s", result.value.(map[string]interface{})["name"].(string)) // Correctly prints "12345"
}

1
标题应该是:“将 JSON 转换为 Go interface{}”吗? - Matt Harrison
是的,那就是我想说的。 - a3onstorm
2个回答

2
简化版,不行,但你有几个选项。
1. 将 `A.Value` 改为使用 `B` 而不是 `interface{}`。 2. 在 `A` 中添加一个函数,如果 `A.Value` 不是 `B`,则将其从映射转换为 `B`。 3. 使用 `encoding/gob` 并将字节存储在 memcache 中,然后使用类似 `NewA(b []byte) *A` 的函数将其转换回来。
对于使用 `gob`,你必须先向其注册每个结构体,然后再进行编码/解码,example
func init() {
    //where you should register your types, just once
    gob.Register(A{})
    gob.Register(B{})
}
func main() {
    var (
        buf bytes.Buffer
        enc = gob.NewEncoder(&buf)
        dec = gob.NewDecoder(&buf)
        val = A{B{"name", "id"}}
        r   A
    )
    fmt.Println(enc.Encode(&val))
    fmt.Println(dec.Decode(&r))
    fmt.Printf("%#v", r)
}

2
嗯,我想我会尝试使用gob。那个函数写起来很麻烦,而且只会占用空间,更不用说错误检查了。 - a3onstorm
嗯,我甚至不确定编码/GOB是否允许您存储接口的基础类型...也许仍然需要编写该函数。 - a3onstorm
1
然而,您必须使用gob.Register为每种类型进行注册。 - OneOfOne
哦,太棒了,看文档的时候错过了这个,我直接跳到编码器了。 - a3onstorm

2

JSON无法编码Go语言中的类型信息深度,因此在反序列化时,您将始终获得以下基本类型:

bool,用于JSON布尔值

float64,用于JSON数字

string,用于JSON字符串

[]interface{},用于JSON数组

map[string]interface{}],用于JSON对象

JSON null的nil

来自Go文档:http://golang.org/pkg/encoding/json/#Unmarshal

如果您对需要的类型有了解,则可以编写一些方法在反序列化时构造正确的变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接