I'am trying to develop simple chat application. And User talks coming from webservice like this json. And I unmarshaling this json as map[string]interface{}. My question is I am trying to get all "talk_messages" in for loop. But I can't.
{
"talk_id": 0,
"receiver_id": 1,
"receiver_name":"Jack",
"sender_id": 0,
"talk_messages":[
{
"message_id": 0,
"body": "Helooo",
"send_date": "12/3/2017 4:57:15 PM",
"sender_id": 0,
"talk_id": 0
},
{
"message_id": 1,
"body": "Helooo",
"send_date": "12/3/2017 4:58:15 PM",
"sender_id": 1,
"talk_id": 0
},
{
"message_id": 2,
"body": "Whatsapp",
"send_date": "12/3/2017 4:59:22 PM",
"sender_id": 0,
"talk_id": 0
},
{
"message_id": 3,
"body": "Lorem impus",
"send_date": "12/3/2017 5:01:15 PM",
"sender_id": 1,
"talk_id": 0
}
]
}
here is my for loop. What is my problem?
var talkData map[string]interface{}
if unMarshalError := json.Unmarshal([]byte(data), &talkData); unMarshalError != nil {
fmt.Println("Talk initialize error :", unMarshalError)
}
idString := fmt.Sprintf("%v", talkData["talk_id"])
talk.id, _ = strconv.ParseInt(idString, 10, 64)
talk.playerOneId = fmt.Sprintf("%v", talkData["receiver_id"])
talk.playerTwoId = fmt.Sprintf("%v", talkData["sender_id"])
talk.receiverName = fmt.Sprintf("%v", talkData["receiver_name"])
for _, val := range talkData["talk_messages"] {
fmt.Println(val)
}
fmt.Println(talk.id, talk.playerOneId, talk.playerTwoId)
Since you're unmarshaling into a generic value (map[string]interface{}
) you'll need to use a type assertion to convert the value referenced by the "talk_messages" key into a slice of generic types ([]interface{}
) so they can be iterated using the "range" keyword, e.g.:
messages := talkData["talk_messages"].([]interface{})
// assert a slice type --------------^^^^^^^^^^^^^^^^
for i, message := range messages {
fmt.Printf("OK: message %d => %s
", i, message)
}
Even better, since you know the structure of the data ahead of time, and assuming it is consistent, you could define struct types in which to marshal that data directly and not have to worry about the interface{}
type at all:
type TalkData struct {
Id int `json:"talk_id"`
ReceiverId int `json:"receiver_id"`
ReceiverName string `json:"receiver_name"`
SenderId int `json:"sender_id"`
Messages []TalkMessage `json:"talk_messages"`
}
type TalkMessage struct {
Id int `json:"message_id"`
Body string `json:"body"`
SendDate string `json:"send_date"`
SenderId int `json:"sender_id"`
TalkId int `json:"talk_id"`
}
talkData := &TalkData{}
err := json.Unmarshal([]byte(data), &talkData)
if err != nil {
// Handle err...
}
for i, message := range talkData.Messages {
// Process message...
}
Also, as mentioned by commenters, you should handle errors in some way other than simply printing them otherwise the program will do unexpected things.