2017-12-15 3 views
-2

簡単なチャットアプリケーションを開発しようとしています。そして、このjsonのようなWebサービスからのユーザーの会話。そして、このjsonをマップ[文字列]インターフェース{}としてアンマーシャリングします。私の質問は、forループですべての "talk_messages"を取得しようとしていることです。しかし、私はできません。ゴランオーバーレンジインターフェース{}

{ 
"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 
    } 
] 
} 

ここはmy forループです。私の問題は何ですか?

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) 
+0

あなたの出力は何ですか、あなたは何を期待していますか?また、メッセージの形式を正確に知っているように見えますが、なぜ定義された構造体に解析しないのでしょうか? – Marc

+0

Goは静的に型指定されています。インタフェース{}は反復可能ではありません。インターフェース{}を使用すべきではありません。または、たとえばにアサーションを入力する必要があります。適切なタイプのスライス。 – Volker

+0

'map [string]インターフェース{}'へのアンマーシャリングは、JSONの構造やフォールバックテクニックを知らない場合にのみ便利です。 JSONが信頼できる既知の構造を持っている場合は、それをマッチング構造にアンマーシャリングします。 – Kaedys

答えて

1

あなたは、一般的な値(map[string]interface{})に非整列化しているので、あなたは、ジェネリック型([]interface{})のスライスに「talk_messages」キーによって参照値を変換するためにtype assertionを使用する必要がありますので、彼らはすることができます「範囲」キーワードを使用して反復すること、例えば:

messages := talkData["talk_messages"].([]interface{}) 
// assert a slice type --------------^^^^^^^^^^^^^^^^ 

for i, message := range messages { 
    fmt.Printf("OK: message %d => %s\n", i, message) 
} 

さらに良いことに、あなたが事前にデータの構造を知って、それが一貫していると仮定しているので、あなたは構造体型れ、そのデータをマーシャリングするために定義することができます直接interface{}タイプについて心配する必要はありません。

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

また、コメント作成者が述べたように、単純に印刷する以外の方法でエラーを処理する必要があります。