2017-05-18 1 views
0

J'essaie d'obtenir les valeurs JSON qui sont passées en tant que message PubNub sur la fin d'abonnement. le code pour cela estconversion d'interface: interface {} est float64 pas [] interface {} PubNub

package main 

import (
    "encoding/json" 
    "flag" 
    "fmt" 
    "github.com/pubnub/go/messaging" 
) 

type DeployMessages struct { 
    Server string 
    Repo string 
} 

type PNMessage struct { 
    Messages []DeployMessages 
    Id  string 
    Channel string 
} 

func main() { 
    publishKey := flag.String("pub", "demo", "publish key") 
    subscribeKey := flag.String("sub", "demo", "subscribe key") 

    channels := flag.String("channels", "channel1, channel2", "channels to subscribe to") 

    pubnub := messaging.NewPubnub(*publishKey, *subscribeKey, "", "", false, "", nil) 

    successChannel := make(chan []byte) 
    errorChannel := make(chan []byte) 

    go pubnub.Subscribe(*channels, "", successChannel, false, errorChannel) 

    subscribeHandler(successChannel, errorChannel, "Subscribe") 
} 

func (pnm *PNMessage) UnmarshalJSON(bs []byte) error { 
    var arr []interface{} 
    err := json.Unmarshal(bs, &arr) 
    if err != nil { 
     return err 
    } 
    messages := arr[0].([]interface{}) 
    pnm.Messages = make([]DeployMessages, len(messages)) 
    for i, m := range messages { 
     pnm.Messages[i].Server = m.(map[string]interface{})["server"].(string) 
     pnm.Messages[i].Repo = m.(map[string]interface{})["repo"].(string) 
    } 
    pnm.Id = arr[1].(string)  
    pnm.Channel = arr[2].(string) 
    return nil 
} 

func subscribeHandler(successChannel, errorChannel chan []byte, action string) { 

    for { 
     select { 
     case response, ok := <-successChannel: 
      if !ok { 
       break 
      } 
      if string(response) != "[]" { 
       message := PNMessage{} 
       err := json.Unmarshal([]byte(response), &message) 
       if err != nil { 
        break 
       } 
       fmt.Println(fmt.Sprintf("%s Response: %s ", action, response)) 
       fmt.Println("") 
      } 

     case failure, ok := <-errorChannel: 
      if !ok { 
       break 
      } 
      if string(failure) != "[]" { 
       if true { 
        fmt.Printf("%s Error Response: %s ", action, failure) 
        fmt.Println("") 
       } 
      } 

     case <-messaging.SubscribeTimeout(): 
      fmt.Printf("Subscirbe request timeout") 
     } 
    } 
} 

Le format du message est le suivant

[[{"Repo":"images","Server":"production"}], "149514560987662985", "channel1"]

Cela jette la panique suivante

panic: interface conversion: interface {} is float64, not []interface {} [recovered] panic: interface conversion: interface {} is float64, not []interface {}

goroutine 1 [running]: encoding/json.(*decodeState).unmarshal.func1(0xc042065c20) C:/Go/src/encoding/json/decode.go:170 +0xf1 panic(0x6548e0, 0xc042009440) C:/Go/src/runtime/panic.go:489 +0x2dd main.(*PNMessage).UnmarshalJSON(0xc0420093c0, 0xc042009300, 0x3d, 0x40, 0x0, 0xb35198) C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:43 +0x499 encoding/json.(*decodeState).array(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x16) C:/Go/src/encoding/json/decode.go:489 +0xbe4 encoding/json.(*decodeState).value(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x16) C:/Go/src/encoding/json/decode.go:399 +0x28e encoding/json.(*decodeState).unmarshal(0xc04205b320, 0x64e6a0, 0xc0420093c0, 0x0, 0x0) C:/Go/src/encoding/json/decode.go:184 +0x221 encoding/json.Unmarshal(0xc042009300, 0x3d, 0x40, 0x64e6a0, 0xc0420093c0, 0xc042065c98, 0x5f82de) C:/Go/src/encoding/json/decode.go:104 +0x14f main.subscribeHandler(0xc042030c00, 0xc042030c60, 0x69c4a4, 0x9) C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:64 +0x222 main.main() C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:34 +0x27e

je faisant référence à la réponse à cette question https://stackoverflow.com/questions/29348262/decoding-pubnub-messages-with-golang-json S'il vous plaît montrez-moi dans la bonne direction ...?

Répondre

2

Lors de la conversion des données entrantes à []interface{}, cela va être long voyage pour obtenir le type de données d'origine. Voici le code de travail:

package main 

import (
    "encoding/json" 
    "fmt" 
) 

type DeployMessage struct { 
    Server string 
    Repo string 
} 

type PNMessage struct { 
    Messages []DeployMessage 
    Id  string 
    Channel string 
} 

// testing to marshal this json 
func main() { 
    // imagine if we have receive our data here. 
    data := []byte(`[[{"Repo":"images","Server":"production"}], "149514560987662985", "channel1"]`) 

    var getData []interface{} 
    err := json.Unmarshal(data, &getData) 
    if err != nil { 
     panic(err) 
    } 
    fmt.Printf("result getData = %+v\n", getData[0]) 

    getData2 := getData[0].([]interface{}) 
    fmt.Printf("result getData = %+v\n", getData2[0]) 

    getData3 := getData2[0].(map[string]interface{}) 

    var deployMessages []DeployMessage 
    deployMessages = append(deployMessages, DeployMessage{Server: getData3["Server"].(string), Repo: getData3["Repo"].(string)}) 

    pNMessage := PNMessage{ 
     Messages: deployMessages, 
     Id:  getData[1].(string), 
     Channel: getData[2].(string), 
    } 

    fmt.Printf("result = %+v\n", pNMessage) 

} 

Le code ci-dessus fonctionnera mais je ne l'aime pas. https://play.golang.org/p/U6slzSgaxu

Vous pouvez raccourcir le code assert vos données comme ceci:

getData2 := getData[0].([]interface{})[0].(map[string]interface{}) 
repo := getData2["Repo"].(string) // this will get the value of Repo in string. 

sortie finale:

result = {Messages:[{Server:production Repo:images}] Id:149514560987662985 Channel:channel1} 
1

Selon le message de panique que vous avez collé, erreur semble se produire dans:

C:/Users/olmadmin/Documents/work/Go/src/DeploymentServer/main.go:43 

qui semble correspondre à cette ligne:

messages := arr[0].([]interface{}) 

Vous semblez être attendre cette position à la array pour contenir un autre tableau, mais apparemment vous obtenez un float64 là, et donc l'erreur:

interface conversion: interface {} is float64, not []interface {} 

Vous pouvez ajouter un peu de débogage pour imprimer ce que vous obtenez en arr à ce moment-là, de sorte que vous pouvez affirmer le type en conséquence en ajoutant ceci avant que la ligne 43:

fmt.Printf("arr: %#v\n", arr) 
+0

sa sortie vide: arr: [] Ce – ozfive

+0

est étrange. Si c'est un tableau vide, alors la ligne suivante devrait lancer une erreur "index out of range" au lieu de celle de float64. Obtenez-vous toujours l'erreur float64 même lorsque cela imprime un tableau vide? Et les numéros de ligne dans votre message sont-ils cohérents avec ceux de votre programme d'origine? – eugenioy