douba4824 2014-07-24 21:30
浏览 14
已采纳

将JSON解组到Go接口{}

I have this struct with a field of type interface{}. In the process of caching it using memcached (https://github.com/bradfitz/gomemcache), the struct is marshalled into a JSON, which is then unmarshalled back into the struct when retrieved from the cache. The resulting interface{} field inevitably points to an object of type map[string]interface{} (as in, the interface{} field can only type asserted as map[string]interface{}), the marshalling and unmarshalling process not having preserved the type information. Is there any way to save this information in the marshalling process, in such a way that it can be unmarshalled properly? Or do I have to use some other codec or something?

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

2条回答 默认 最新

  • doujuxin7392 2014-07-24 21:40
    关注

    Short version, no you can't do that, you have few options though.

    1. Change A.Value to use B instead of interface{}.
    2. Add a function to A that converts A.Value from a map to B if it isn't already B.
    3. Use encoding/gob and store the bytes in memcache then convert it back with a function like NewA(b []byte) *A.

    For using gob, you have to register each struct with it first before encoding / decoding, 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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 vue3加ant-design-vue无法渲染出页面
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 路易威登官网 里边的参数逆向
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决
  • ¥15 processing提取音乐节奏
  • ¥15 gg加速器加速游戏时,提示不是x86架构
  • ¥15 python按要求编写程序