使用golang JSON解码PubNub消息

时间:2015-03-30 14:03:42

标签: json go pubnub

我一直试图从PubNub解析这个JSON消息而没有任何运气:

type PubNubMessage struct {
    body []string
}

[[{"text":"hey"}],"1231212412423235","channelName"]
json: cannot unmarshal array into Go value of type main.PubNubMessage

有没有人知道如何在golang中解码这些复杂类型?

4 个答案:

答案 0 :(得分:1)

简短的回答是,您无法直接将非同类型的JSON数组(根据您的示例)解组为golang结构。

答案很长,你应该为你的PubNubMessage类型定义一个(m *PubNubMessage) UnmarshalJSON([]byte) error method,它将JSON字符串解组为interface{},然后使用类型断言来确保预期的格式并填充结构。

例如:

type TextMessage struct {
  Text string
}

type PubNubMessage struct {
  Messages []TextMessage
  Id       string
  Channel  string
}

func (pnm *PubNubMessage) UnmarshalJSON(bs []byte) error {
  var arr []interface{}
  err := json.Unmarshal(bs, &arr)
  if err != nil {
    return err
  }
  messages := arr[0].([]interface{}) // TODO: proper type check.
  pnm.Messages = make([]TextMessage, len(messages))
  for i, m := range messages {
    pnm.Messages[i].Text = m.(map[string]interface{})["text"].(string) // TODO: proper type check.
  }
  pnm.Id = arr[1].(string) // TODO: proper type check.
  pnm.Channel = arr[2].(string) // TODO: proper type check.
  return nil
}

  // ...
  jsonStr := `[[{"text":"hey"},{"text":"ok"}],"1231212412423235","channelName"]`
  message := PubNubMessage{}
  err := json.Unmarshal([]byte(jsonStr), &message)

答案 1 :(得分:0)

您可以在UnmarshalJSON上定义PubNubMessage以提供自定义JSON反序列化。你可能应该为你的目的调整一点,但一般的想法是你只需将这个json数组解组成一个切片,然后从中获取所有必要的部分。

Playground example此处

答案 2 :(得分:0)

你的json是异构数组。您至少可以将PubNubMessage定义为

type PubNubMessage []interface{}然后使用类型断言text:= (message[0].([]interface {})[0].(map[string]interface {}))["text"].(string)访问数据 工作示例https://play.golang.org/p/xhwbE2ora1

type PubNubMessage []json.RawMessage以及json.Unmarshal(jsonBlob, &message)之后' json.Unmarshal(message [0],structured.text)'每个和平分开的 https://play.golang.org/p/TJ0DfiweGo

答案 3 :(得分:0)

使用encoding/json包的替代方法更容易解析具有不同类型值的JSON数组。例如,尝试fastjson。它可以轻松(快速)解析这些数组:

input := `[[{"text":"hey"}],"1231212412423235","channelName"]`

var p fastjson.Parser
v, err := p.Parse(input)
if err != nil {
    log.Fatal(err)
}
a := v.GetArray()
for _, vv := range a {
    switch vv.Type() {
    case fastjson.TypeArray:
        fmt.Printf("array %s\n", vv)
    case fastjson.TypeString:
        fmt.Printf("string %s\n", vv)
    }
}

此外,fastjson提供了便于从JSON获取所需字段的功能:

// get v[0].text as Go byte slice
text := v.GetStringBytes("0", "text")

// get v[2]
channelName := v.Get("2")  // this is the same as v.GetArray()[2]