L
L
linuxoid_inrus2020-11-06 17:31:09
go
linuxoid_inrus, 2020-11-06 17:31:09

How to parse Telegram JSON correctly?

I used to parse JSON normally in this way, but now something went wrong

package main

import (
  "encoding/json"
  "fmt"
  "io/ioutil"
  "net/http"
)

func main(){
  token := "d"
  url := fmt.Sprintf("https://api.telegram.org/bot%s/getUpdates", token)
  res, err := http.Get(url)
  if err != nil {
    panic(err)
  }

    bodyBytes, err := ioutil.ReadAll(res.Body)

  var data map[string]interface{}
    json.Unmarshal(bodyBytes, &data)

  fmt.Println(data["result"].(map[string]interface{})["chat"])


}


Mistake:
panic: interface conversion: interface {} is []interface {}, not map[string]interface {}

goroutine 1 [running]:
main.main()

Answer the question

In order to leave comments, you need to log in

2 answer(s)
E
Evgeny Samsonov, 2020-11-07
@linuxoid_inrus

The first option is to parse manually. Looks like that

package main

import (
  "fmt"
  "encoding/json"
  "log"
)

func main() {
  bodyBytes := []byte(`{"ok":true,"result":[{"update_id":715296593,
"message":{"message_id":5,"from":{"id":362268798,"is_bot":false,"first_name":"\u041a\u043e\u0442\ud83d\udd25","username":".....","language_code":"ru"},"chat":{"id":362268798,"first_name":"\u041a\u043e\u0442\ud83d\udd25","username":"....","type":"private"},"date":1604728384,"text":"/start","entities":[{"offset":0,"length":6,"type":"bot_command"}]}}]}`)

  var data map[string]interface{}
  err := json.Unmarshal(bodyBytes, &data)
  if err != nil {
    log.Fatal(err)
  }
  
  result, ok := data["result"].([]interface{})
  if !ok {
    log.Fatal("Failed to type-cast result")
  }
  firstResult, ok := result[0].(map[string]interface{})
  if !ok {
    log.Fatal("Failed to type-cast first result")
  }
  message, ok := firstResult["message"].(map[string]interface{})
  if !ok {
    log.Fatal("Failed to type-cast message")
  }
  chat, ok := message["chat"].(map[string]interface{})
  if !ok {
    log.Fatal("Failed to type-cast chat")
  }

  fmt.Println("id =", chat["id"])
  fmt.Println("type = ", chat["type"])
  fmt.Println("username = ", chat["username"])
  fmt.Println("first_name = ", chat["first_name"])
}

https://play.golang.org/p/ZDis4Y9be31
The second option is more correct and convenient. Describe the response structure and parse json into this structure
package main

import (
  "fmt"
  "encoding/json"
  "log"
)

type Response struct {
  Results []Result `json:"result"`
}

type Result struct {
  Message Message `json:"message"`
}

type Message struct {
  Chat Chat `json:"chat"`
}

type Chat struct {
   ID int `json:"id"`
   FirstName string `json:"first_name"`
   UserName string `json:"username"`
   Type string `json:"type"`
}

func main() {
  bodyBytes := []byte(`{"ok":true,"result":[{"update_id":715296593,
"message":{"message_id":5,"from":{"id":362268798,"is_bot":false,"first_name":"\u041a\u043e\u0442\ud83d\udd25","username":".....","language_code":"ru"},"chat":{"id":362268798,"first_name":"\u041a\u043e\u0442\ud83d\udd25","username":"....","type":"private"},"date":1604728384,"text":"/start","entities":[{"offset":0,"length":6,"type":"bot_command"}]}}]}`)

  var response Response
  err := json.Unmarshal(bodyBytes, &response)
  if err != nil {
    log.Fatal(err)
  }

  fmt.Println("id =", response.Results[0].Message.Chat.ID)
  fmt.Println("type = ", response.Results[0].Message.Chat.Type)
  fmt.Println("username = ", response.Results[0].Message.Chat.UserName)
  fmt.Println("first_name = ", response.Results[0].Message.Chat.FirstName)
}

https://play.golang.org/p/qrROYHjn-Cc

A
Alexander Pavlyuk, 2020-11-06
@pav5000

You get a []interface{} slice, and you try to
cast it to map[string]interface{}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question