我一直试图从PubNub解析这个JSON消息而没有任何运气:
type PubNubMessage struct {
body []string
}
[[{"text":"hey"}],"1231212412423235","channelName"]
json: cannot unmarshal array into Go value of type main.PubNubMessage
有没有人知道如何在golang中解码这些复杂类型?
答案 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数组解组成一个切片,然后从中获取所有必要的部分。
答案 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]