将其解组为接口类型

huangapple go评论105阅读模式
英文:

Unmarshall into an interface type

问题

我预期以下代码将打印出一个类型为struct J的对象,但实际上它打印出了一个类型为map[string]interface{}的映射对象。我可以理解为什么会这样,但是当我运行reflect.ValueOf(i).Kind()时,它返回的是Struct,所以我有点觉得Unmarshal方法应该返回类型J而不是一个映射。有人可以给我解释一下吗?

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)
}
英文:

I expected below code to print an object of type struct J, however it prints a map object of type map[string]interface{}. I can feel why it acts like that, however when I run, reflect.ValueOf(i).Kind(), it returns Struct, so it kinda gives me the impression that Unmarshal method should return type J instead of a map. Could anyone enlighten me ?

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)

}

答案1

得分: 3

你传递给Unmarshal的类型不是*J,而是*interface{}

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

  • bool,用于JSON布尔值
  • float64,用于JSON数字
  • string,用于JSON字符串
  • []interface{},用于JSON数组
  • map[string]interface{},用于JSON对象
  • nil,用于JSON null

几乎没有理由使用指向接口的指针。如果你发现自己使用指向接口的指针,并且不知道确切的原因,那么很可能是个错误。如果你想要解组到J,那么直接传递它即可。如果你需要将其赋值给一个中间接口,确保使用指向原始值的指针,而不是指向其接口的指针。

j := J{}
var i interface{} = &j

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

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

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

希望对你有帮助!

英文:

The type you're passing into Unmarshal is not *J, you're passing in an *interface{}.

When the json package reflects what the type is of the pointer it received, it sees interface{}, so it then uses the default types of the package to unmarshal into, which are

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

There is almost never a reason to use a pointer to an interface. If you find yourself using a pointer to an interface, and you don't know exactly why, then it's probably a mistake. If you want to unmarshal into J, then pass that in directly. If you need to assign that to an intermediary interface, make sure you use a pointer to the original value, not a pointer to its interface.

http://play.golang.org/p/uJDFKfSIxN

j := J{}
var i interface{} = &j

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

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

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

答案2

得分: 2

这是预期的行为:json.Unmarshal不是给一个指向正确类型的内存位置的指针,而是给了一个指向类型为interface{}的内存位置的指针。它可以在这个位置存储任何类型的数据,根据JSON定义的类型进行存储。

可以这样理解:

  1. Unmarshal 获取一个类型为interface{}的数据 v 的存储位置。
  2. Unmarshal 检测到一个以JSON编码的映射。
  3. Unmarshal 发现目标类型是interface{}类型,创建一个Go映射并将其存储在 v 中。

如果你给它一个不同于interface{}的类型,过程将如下所示:

  1. Unmarshal 获取一个类型为struct main.J的数据 v 的存储位置。
  2. Unmarshal 检测到一个以JSON编码的映射。
  3. Unmarshal 发现目标类型是struct main.J,并开始递归地将数据适配到该类型。

关键点在于,初始赋值

var i interface{} = j

json.Unmarshal 中完全被忽略。

英文:

This is expected behavior: instead of giving json.Unmarshal a pointer to a properly typed place in memory you give it a pointer to a place in memory with type interface{}. It can essentially store anything in there under the type the JSON defines, so it does just that.

See it like this:

  1. Unmarshal gets a place to store the data v with type interface{}
  2. Unmarshal detects a map encoded as JSON
  3. Unmarshal sees that the target type is of type interface{}, creates a go map from it and stores it in v

If you would have given it a different type than interface{} the process would have looked like this:

  1. Unmarshal gets a place to store the data v with type struct main.J
  2. Unmarshal detects a map encoded as JSON
  3. Unmarshal sees that the target type is struct main.J and begins to recursively fit the data to the type

The main point is, that the initial assignment

var i interface{} = j

is completely ignored by json.Unmarshal.

huangapple
  • 本文由 发表于 2016年3月19日 00:37:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/36089738.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定