Go 将接口{}从JSON转换为多种具体类型之一

Go 将接口{}从JSON转换为多种具体类型之一,go,interface,Go,Interface,我一直在四处寻找这个问题的解决方案,但在这里一直找不到。我不确定这是否可能,但值得一问 我有一个接口,我的应用程序从服务器读取JSON数据。可能会返回响应的类型很少,所以我使用interface{}来使用它 在将json字节解组到接口{}之后,如何将其转换为具体类型?如果失败,我想检查下一种对话类型,直到对话成功 它看起来像这样(为了简洁起见删除了一些代码) type foorer接口{ Foo() } 键入结构{} func(a*a)Foo(){..} 类型B结构{} func(b*b)Foo

我一直在四处寻找这个问题的解决方案,但在这里一直找不到。我不确定这是否可能,但值得一问

我有一个接口,我的应用程序从服务器读取JSON数据。可能会返回响应的类型很少,所以我使用
interface{}
来使用它

在将json字节解组到
接口{}
之后,如何将其转换为具体类型?如果失败,我想检查下一种对话类型,直到对话成功

它看起来像这样(为了简洁起见删除了一些代码)

type foorer接口{
Foo()
}
键入结构{}
func(a*a)Foo(){..}
类型B结构{}
func(b*b)Foo(){..}
//resp是io.ReadCloser
func重量级软件(resp){
var parsedResp接口{}
bytesData,err:=ioutil.ReadAll(resp)
Unmarshal(bytesData,parsedResp)
//将parsedResp转换为具体类型,它可能是a或B结构
//试试A,如果失败,试试B。
...
concreteType.Foo()
}
我已经检查了类型断言和类型转换,但无法使其正常工作

围棋可以吗

JSON响应内容示例

A:
{
  "data": {
    "access_key": "AKIA...",
    "secret_key": "xlCs...",
  }
}

B:
{
  "data": {
    "data": {
      "foo": "bar"
    },
    "metadata": {
      ...
    }
  }
}

你有选择。没有一个是完美的

一个是,如前所述,只需查看地图内部的钥匙。我写了一个这样的例子。它的目的是要有教育意义,但不是特别有效率或任何东西

另一种方法是使用
json.RawMessage
稍微延迟解析。我写了一个这样的例子。请注意,我是如何求助于解码器中各种
struct
s的指针成员的。这会让事情变得烦人:您可能只想为解码使用指针化的数据类型,而在选择类型后使用非指针类型。但它确实允许您直接(通过struct标记)使用更多的json包


还有一种方法是使用
json.NewDecoder
来获取流解码器,并对其进行处理。这可能是最健壮的方法,但也是最棘手的。

如何将其转换为具体类型?--手动。由于您正在使用
interface{}
作为解组的目标,因此结果将是
map[string]interface{}
[]interface{}
或某些原语。因此,将您的
parsedResp
,将assert键入其中一种可能的类型,然后每个元素(如果有)都会这样做,依此类推。。。然后从你收集的数据中构建具体的类型。或者首先不要使用
接口{}
。什么结构
interface{}
不是一个结构,执行
json.Unmarshal(data,&dest)
其中dest的类型为
interface{}
且没有初始化的动态类型,将无法神奇地看出您想要
a
B
。i、 e.
parseResp
中没有结构。如果您解组到并
interface{}
中,您将获得JSON对象的
map[string]interface{}
。您需要从中进行转换,或者直接解组到正确的具体类型。@ChenA。是的,如果
数据
像您显示的那样随机,并且您无法预先知道json字节代表的具体类型,那么您必须做一件难看的事情,在
map[string]interface{}
中摸索。请参阅,以获取有关解组未知类型的一些提示。感谢提供详细的示例。我正在考虑重构它。有一个通用结构来解析json(如第二个示例),然后根据预期的内容确定它是哪个结构。你有一个
json.NewDecoder
的例子吗?没有,NewDecoder看起来是最棘手的一个,我就停在这一点上了。:-)