我一直在尝试从PubNub解析这个JSON消息,但没有任何运气:
type PubNubMessage struct {
body []string
}
[[{"text":"hey"}],"1231212412423235","channelName"]
json: cannot unmarshal array into Go value of type main.PubNubMessage
有人知道如何在戈兰解码这种复杂的类型吗?
简单的答案是,您不能直接将非同质类型的JSON数组(根据您的示例)解组为golang结构。
详细的答案是,您应该为PubNubMessage类型定义一个(m *PubNubMessage) UnmarshalJSON([]byte) error
方法,该方法将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)
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
您可以在PubNubMessage
上定义UnmarshalJSON
,以提供自定义的JSON反序列化。出于您的目的,您可能应该对此进行一点调整,但总体思路是,您只需将这个json数组分解为一个切片,然后从中获取所有必要的部分。
此处的游乐场示例
使用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 %sn", vv)
case fastjson.TypeString:
fmt.Printf("string %sn", 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]