从[]interface{}中解析任何类型吗?

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

UnmarshalJSON any type from []interface{} possible?

问题

当你将JSON解组为[]interface{}时,除了一些标准类型(如bool、int和string)之外,是否有任何自动检测类型的方法?

我注意到以下情况,假设我将[uuid.UUID, bool]进行编组,然后得到的JSON如下所示:

[[234,50,7,116,194,41,64,225,177,151,60,195,60,45,123,106],true]

当我再次解组时,通过reflect显示的类型如下:

[]interface{}, bool

我不明白为什么它选择了[]interface{}。如果它无法检测到类型,那么它不应该至少是interface{}吗?

无论如何,我的问题是,当目标类型为[]interface{}时,是否可能解组任何类型?对于标准类型(如string、bool、int),似乎可以工作,但对于自定义类型,我认为这是不可能的,对吗?你可以定义自定义的JSON编组/解组方法,但这仅适用于将其解码为目标类型,以便可以查找要使用的自定义编组/解组方法。

英文:

When you unmarshal JSON to []interface{} is there any way to automatically detect the type besides some standard types like bool, int and string?

What I noticed is the following, Let's say I marshal [uuid.UUID, bool] then the JSON I get looks like:

[[234,50,7,116,194,41,64,225,177,151,60,195,60,45,123,106],true]

When I unmarshal it again, I get the types as shown through reflect:

[]interface{}, bool

I don't understand why it picked []interface{}. If it cannot detect it, shouldn't it be at least interface{}?

In any case, my question is, is it possible to unmarshal any type when the target is of type []interface{}? It seems to work for standard types like string, bool, int but for custom types I don't think that's possible, is it? You can define custom JSON marshal/unmarshal methods but that only works if you decode it into a target type so that it can look up which custom marshal/unmarshal methods to use.

答案1

得分: 3

你可以将任何类型解组为interface{}类型的值。如果你使用[]interface{}类型的值,你只能将JSON数组解组到其中,但是是的,数组的元素可以是任何类型。

由于你使用的是interface{}[]interface{}类型,是的,类型信息是不可用的,这取决于encoding/json包选择最合适的类型。例如,对于JSON对象,它会选择map[string]interface{}类型。默认类型的完整列表在json.Unmarshal()中有文档记录:

为了将JSON解组为接口值,Unmarshal将其中之一存储在接口值中:

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

显然,如果你的JSON编组/解组逻辑需要一些预处理/后处理,json包将无法奇迹般地找到它。它只能在你解组为特定类型的值(实现了json.Unmarshaler)时了解到这些信息。json包仍然能够将它们解组为默认类型,但是自定义逻辑显然不会对它们运行。

英文:

You can unmarshal any type into a value of type interface{}. If you use a value of type []interface{}, you can only unmarshal JSON arrays into it, but yes, the elements of the array may be of any type.

Since you're using interface{} or []interface{}, yes, type information is not available, and it's up to the encoding/json package to choose the best it sees fit. For example, for JSON objects it will choose map[string]interface{}. The full list of default types is documented in json.Unmarshal():

> To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:
>
> 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

Obviously if your JSON marshaling/unmarshaling logic needs some pre- / postprocessing, the json package will not miraculously find it out. It can know about those only if you unmarshal into values of specific types (which implement json.Unmarshaler). The json package will still be able to unmarshal them to the default types, but custom logic will obviously not run on them.

huangapple
  • 本文由 发表于 2017年1月27日 16:59:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/41890150.html
匿名

发表评论

匿名网友

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

确定