Json 解组为接口类型

Json 解组为接口类型,json,go,unmarshalling,Json,Go,Unmarshalling,我希望下面的代码打印structJ类型的对象,但是它打印map[string]interface{}类型的映射对象。我能感觉到为什么它会这样,但是当我运行reflect.ValueOf(I).Kind()时,它返回Struct,所以它给我的印象是Unmarshal方法应该返回typeJ,而不是map。有谁能启发我吗 type J struct { Text string } func main() { j := J{} var i interface{} = j

我希望下面的代码打印struct
J
类型的对象,但是它打印
map[string]interface{}
类型的映射对象。我能感觉到为什么它会这样,但是当我运行reflect.ValueOf(I).Kind()时,它返回
Struct
,所以它给我的印象是
Unmarshal
方法应该返回type
J
,而不是map。有谁能启发我吗

type J struct {
    Text string
}

func main() {
    j := J{}
    var i interface{} = j

    js := "{\"Text\": \"lala\"}"


    json.Unmarshal([]byte(js), &i)

    fmt.Printf("%#v", i)

}

传递到
解组的类型不是
*J
,而是传递到
*接口{}

json
包反映它接收到的指针的类型时,它会看到
接口{}
,因此它会使用包的默认类型进行解组,这些类型是

bool, for JSON booleans
float64, for JSON numbers
string, for JSON strings
[]interface{}, for JSON arrays
map[string]interface{}, for JSON objects
nil for JSON null
几乎没有理由使用指向接口的指针。如果您发现自己正在使用指向接口的指针,并且不知道确切原因,那么这可能是一个错误。如果要将其解组到
J
,请直接传入。如果需要将其分配给中间接口,请确保使用指向原始值的指针,而不是指向其接口的指针


这是预期的行为:不是给
json.Unmarshal
一个指向内存中正确键入的位置的指针,而是给它一个指向内存中具有类型
接口{}
的位置的指针。它基本上可以在JSON定义的类型下存储其中的任何内容,所以它就是这样做的

这样看:

  • Unmarshal
    使用类型
    interface{}
  • Unmarshal
    检测编码为JSON的映射
  • Unmarshal
    看到目标类型为
    interface{}
    类型,从中创建一个go映射并将其存储在
    v
  • 如果您给它一个不同于
    接口{}
    的类型,则该过程将如下所示:

  • Unmarshal
    获取一个位置来存储类型为
    struct main.J的数据
    v
  • Unmarshal
    检测编码为JSON的映射
  • Unmarshal
    看到目标类型是
    struct main.J
    ,并开始递归地将数据拟合到该类型
  • 主要的一点是,初始赋值

    var i interface{} = j
    

    被json.Unmarshal完全忽略了

    是的,我在问题中提到过,我知道。然而,reflect.TypeOf(i)将告诉我们,类型实际上是main.J。它的类型是Struct。所以它返回给我们一张地图是没有意义的。@OzumSafa:除了你没有将
    i
    传递到
    Unmarshal
    之外,你传递的是
    &i
    ,所以类型是
    *接口{}
    ,而不是
    J
    。即使是json包深入查找
    J
    ,您也不会有指向
    J
    的指针,因此无法将其解组。啊,启示是真实的。谢谢。我运行了这个,将
    fmt.Printf(“%#v”,I)
    更改为
    fmt.Printf(“%v”,reflect.ValueOf(I.Kind())
    结果是:map你的答案也很棒,但上面的答案更切题。但是谢谢你。
    var i interface{} = j