小编典典

解组到接口{}中,然后执行类型声明

go

string通过Rabbitmq消息系统获得了。在发送之前,

我使用json.Marshal,将结果转换为string并通过Rabbitmq发送。

我转换和发送的结构可以是:(更改了结构的名称和大小,但这没有关系)

type Somthing1 struct{
   Thing        string    `json:"thing"`
   OtherThing   int64     `json:"other_thing"`
}

要么

type Somthing2 struct{
   Croc        int       `json:"croc"`
   Odile       bool      `json:"odile"`
}

消息完全像a一样经过,string并打印在另一面(某些服务器)

到目前为止,一切正常。现在,我试图将它们转换回它们的结构并声明类型。

第一次尝试是通过:

func typeAssert(msg string) {

 var input interface{}

 json.Unmarshal([]byte(msg), &input)

 switch input.(type){
 case Somthing1:
    job := Somthing1{}
    job = input.(Somthing1)
    queueResults(job)

  case Somthing2:
    stats := Somthing2{}
    stats = input.(Somthing2)
    queueStatsRes(stats)
 default:
}

这是行不通的。当input在拆封后打印它的类型时,我得到map[string]interface{}(?!?)

甚至比这更奇怪,映射键是我得到的字符串,映射值是空的。

我做了其他一些尝试,例如:

 func typeAssert(msg string) {

  var input interface{}

  json.Unmarshal([]byte(msg), &input)

  switch v := input.(type){
  case Somthing1:
    v = input.(Somthing1)
    queueResults(v)

   case Somthing2:
    v = input.(Somthing2)
    queueStatsRes(v)
  default:
}

并且还尝试编写此答案中解释的开关:
Golang:无法在非接口值上键入switch

switch v := interface{}(input).(type)

仍然没有成功…

有任何想法吗?


阅读 260

收藏
2020-07-02

共1个答案

小编典典

功能文档json中显示了包解组到的默认类型Unmarshal

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

由于您要编组为interface{},因此返回的类型将仅来自该集合。该json软件包不了解Something1Something2。您需要从将map[string]interface{}json对象解组为的转换,或者直接解组为所需的struct类型。

如果您不想从通用接口中解压缩数据,或者以某种方式标记数据以便知道期望的类型,则可以迭代地获取json并尝试将其解编为所需的每种类型。

您甚至可以将它们打包到包装结构中,为您进行拆封:

type Something1 struct {
    Thing      string `json:"thing"`
    OtherThing int64  `json:"other_thing"`
}

type Something2 struct {
    Croc  int  `json:"croc"`
    Odile bool `json:"odile"`
}

type Unpacker struct {
    Data       interface{}
}

func (u *Unpacker) UnmarshalJSON(b []byte) error {
    smth1 := &Something1{}
    err := json.Unmarshal(b, smth1)

    // no error, but we also need to make sure we unmarshaled something
    if err == nil && smth1.Thing != "" {
        u.Data = smth1
        return nil
    }

    // abort if we have an error other than the wrong type
    if _, ok := err.(*json.UnmarshalTypeError); err != nil && !ok {
        return err
    }

    smth2 := &Something2{}
    err = json.Unmarshal(b, smth2)
    if err != nil {
        return err
    }

    u.Data = smth2
    return nil
}

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

2020-07-02