【问题标题】:How to unmarshal from interface{} to interface{} in Go如何在 Go 中从 interface{} 解组到 interface{}
【发布时间】:2017-04-10 22:25:00
【问题描述】:
我的系统中有多个节点通过 RPC 进行通信。我正在尝试通过 RPC 将 map[string] interface{} 发送到另一个节点。发送方使用 json.Marshal 接收方使用 json.Unmarshal 获取地图。
假设在发送方,map 包含 [1] => 2,其中 2 是 uint32 类型。
问题是 Unmarshal 尝试查找基础数据的类型,并根据此处 https://blog.golang.org/json-and-go 指定的默认行为将 2 转换为 float64 类型。后来,将 float64 转换为 uint32 会引起恐慌。
我提到了How to unmarshal json into interface{} in golang?。但是为此,我们需要知道数据的类型。在我的情况下,数据可以是任何类型,所以我想将其保留为 interface{}。如何从 interface{} 解组到 interface{}?
【问题讨论】:
标签:
json
go
unmarshalling
【解决方案1】:
很遗憾,您不能使用 encoding/json 包,因为类型信息不会传输,并且如果类型信息不存在,默认情况下 JSON 数字会解组为 float64 类型的值。您需要定义 struct 类型,其中明确声明该字段的类型为 uint32。
或者,您可以选择使用encoding/gob,它确实传输和保留类型信息。看这个例子:
m := map[string]interface{}{"1": uint32(1)}
b := &bytes.Buffer{}
gob.NewEncoder(b).Encode(m)
var m2 map[string]interface{}
gob.NewDecoder(b).Decode(&m2)
fmt.Printf("%T\n%#v\n", m2["1"], m2)
输出(在Go Playground上试试):
uint32
map[string]interface {}{"1":0x1}
gob 的缺点是它是特定于 Go 的,不像独立于语言和平台的 JSON。