解组到接口{},然后执行类型断言 [英] Unmarshaling Into an Interface{} and Then Performing Type Assertion

查看:11
本文介绍了解组到接口{},然后执行类型断言的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过 rabbitmq 消息系统得到一个 string.发送前,

I get a string through a rabbitmq message system. Before sending,

我使用 json.Marshal,将结果转换为 string 并发送rabbitmq.

I use json.Marshal, convert the outcome to string and send through rabbitmq.

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

The structs that I convert and send can be: (changed the names and the size of the structs but it should not matter)

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

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

消息以 string 的形式完美传递并被打印出来在另一端(某些服务器)

The message goes through perfectly as a string and is printed on the other side (some server)

到目前为止,一切正常.现在我正在尝试将它们转换回它们的结构并断言类型.

Up until now everything works. Now I'm trying to convert them back into their structs and assert the types.

第一次尝试是:

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:
}

这不起作用.在 Unmarshaling 后打印 input 的类型时我得到 map[string]interface{} (?!?)

This does not work. When Printing the type of input after Unmarshaling it I get map[string]interface{} (?!?)

更奇怪的是,map key 是我得到的字符串,map value 是空的.

and even stranger than that, the map key is the string I got and the map value is empty.

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

I did some other attempts like:

 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:无法在非接口值上输入开关

and also tried writing the switch like was explained in this answer: Golang: cannot type switch on non-interface value

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

还是没有成功...

有什么想法吗?

推荐答案

json 包 Unmarshals 成的默认类型显示在 Unmarshal 函数文档

The default types that the json package Unmarshals into are shown in the Unmarshal function documentation

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.您需要从 json 对象被解组到的 map[string]interface{} 进行转换,或者直接解组到您想要的结构类型.

Since you're unmarshaling into an interface{}, the returned types will only be from that set. The json package doesn't know about Something1 and Something2. You either need to convert from the map[string]interface{} that the json object is being unmarshaled into, or unmarshal directly into the struct type you want.

如果您不想从通用接口解包数据,或者以某种方式标记数据以便知道预期的类型,则可以迭代地获取 json 并尝试将其解组为您想要的每种类型.

If you don't want to do unpack the data from a generic interface, or somehow tag the data so you know what type to expect, you could iteratively take the json and try to unmarshal it into each type you want.

您甚至可以将它们打包到一个包装器结构中来为您进行解组:

You can even pack those into a wrapper struct to do the unmarshaling for you:

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

这篇关于解组到接口{},然后执行类型断言的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆