Search code examples
gowebsocketgorilla

go websockets with gorilla libs - unknown json response so can't map it


I am a newbee, and I am trying to connect to a website that uses websocket for many things, including a chat. my goal is to get only the chat output and do something with that and ignore the rest.

I know the json I am expecting for the chat, but not for the rest, so when I run the program I get now all the websocket output, but im only interested in:

[null,null,"channel:zRAMDON","message",{"session_id":"ramdon-d655-4ee1-ramdon","body":"TEST!!!!!!!!!!!!!!!!!!!","type":"chat"}]

now I'm using to catch all

var readCHAT []interface{}

go func() {
        for {
            
            err := ws.ReadJSON(&readCHAT)

            if err != nil {
                log.Printf("Error read: %s", err)
                break
            }
            log.Printf("Message received: %+v", readCHAT)
        }
    }()

the problem I have is that I get diff websocket msg's so can't just write a one struct.

a example of websocket I get that I do not need as many others I want to ignore:

[<nil> <nil> channel:zRAMDON naf map[data:map[components:map[0:map[x:18.37785615655833 y:3.849238250917483 z:31.306368728428566] 1:map[x:-2.1127290916182298e-13 y:-14.000000000000544 z:1.6920595533305515e-13] 10:map[x:0 y:0 z:0] 11:map[x:0 y:0 z:0] 12:false 2:map[x:1.0000000000000018 y:1.0000000000000713 z:0.999999999999999] 3:map[avatarSrc:https://somewhere.com/api/v1/avatars/PcJ8Sxb/avatar.gltf?v=63726570330 avatarType:skinnable muted:true] 4:map[left_hand_pose:0 right_hand_pose:0] 5:map[x:0 y:1.6 z:0] 6:map[x:5.21773538958394 y:41.12499999998135 z:-3.292556714059138e-11] 7:map[x:0 y:0 z:0] 8:map[x:0 y:0 z:0] 9:false] creator:f6ee84ab-15af-4bc0-b9df-aa9c71093118 isFirstSync:true lastOwnerTime:1.5933988881835e+12 networkId:m9ms3qv owner:f6ee84ab-15af-4bc0-b9df-aa9c71093118 parent:<nil> persistent:false template:#remote-avatar] dataType:u from_session_id:f6ee84ab-15af-4bc0-b9df-aa9c71093118]]

how can I work with only the json I need if I can't convert it to a struct to use map[] etc etc when I am not sure what I am getting.

IDEAL: if I could just somehow dynamically search the interface and if the json is the one I expect then put it into objets in a struct... or similar..

thanks

[edit]

diff examples that I need to ignore:

[<nil> <nil> channel:zRAMDON naf map[data:map[components:map[0:map[x:4.001814822517539 y:2.644030847036413 z:30.97952900553247] 1:map[x:2.4521572390556376e-13 y:-14.000000000000105 z:8.633353546977925e-15] 10:map[x:0 y:0 z:0] 11:map[x:0 y:0 z:0] 12:false 2:map[x:1 y:1.0000000000000715 z:1.0000000000000009] 3:map[avatarSrc:https://somesite.com/api/v1/avatars/3IADk9x/avatar.gltf?v=63743924756 avatarType:skinnable muted:true] 4:map[left_hand_pose:0 right_hand_pose:0] 5:map[x:0 y:1.6 z:0] 6:map[x:-7.540983606551728 y:111.09374999994142 z:-4.904411738530524e-11] 7:map[x:0 y:0 z:0] 8:map[x:0 y:0 z:0] 9:false] creator:de96a126-cf5f-48b2-8c0c-02d79b4382d5 isFirstSync:true lastOwnerTime:1.5934383934451e+12 networkId:5jwrz57 owner:de96a126-cf5f-48b2-8c0c-02d79b4382d5 parent:<nil> persistent:false template:#remote-avatar] dataType:u from_session_id:de96a126-cf5f-48b2-8c0c-02d79b4382d5]]

another one:

[<nil>  phoenix phx_reply map[response:map[] status:ok]]

another one this one is like the most I get but I DO NOT need, so need to filter all of it out:

[<nil> <nil> channel:zRAMDON naf map[data:map[components:map[0:map[x:4.001814822517539 y:2.644030847036413 z:30.97952900553247] 1:map[x:2.4521572390556376e-13 y:-14.000000000000105 z:8.633353546977925e-15] 10:map[x:0 y:0 z:0] 11:map[x:0 y:0 z:0] 12:false 2:map[x:1 y:1.0000000000000715 z:1.0000000000000009] 3:map[avatarSrc:https://somesite.com/api/v1/avatars/3IADk9x/avatar.gltf?v=63743924756 avatarType:skinnable muted:true] 4:map[left_hand_pose:0

those AND LIKE 100 other ones that are even more different and not even the same patter, if they had all the same pattern but diff content then it will be easy to write a struct and get a idea of the json document.

here is what I actually need:

[null,null,"channel:zRAMDON","message",{"session_id":"ramdon-d655-4ee1-ramdon","body":"TEST!!!!!!!!!!!!!!!!!!!","type":"chat"}]

So I need to somehow get filter/get rid of and then from this response I could maybe write a struct to put in the null, null, channel, message etc

thanks for the help. this is driving me crazy

EDIT2:

ok I have open the websocket network tab of chrome dev tools: I notice there is always an array of 4 elements then this opens to a json at the end. but this json is always diff and the descryptions so far are obscure:

["2", "238", "hub:zWXK8U6", "nafr", {,…}]
0: "2"
1: "238"
2: "room:zRAMDON"
3: "nafr"
4: {,…}
naf: "{"dataType":"um","data":{"d":[{"networkId":"A8AFC029-A3AF-459B-AC89-83557814DEAC","owner":"fa477e9d-7e92-4c1d-9b7b-6e9e0e975495","creator":"","lastOwnerTime":1593446129608,"template":"#static-controlled-media","persistent":true,"parent":null,"components":{"1":169.509434}}]}}"

another similar but diff on 3 element:

"2", "237", "room:zRAMDON", "naf",…]
0: "2"
1: "237"
2: "room:zRAMDON"
3: "naf"
4: {dataType: "u", data: {networkId: "mi2p4c5", owner: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495",…}}
data: {networkId: "mi2p4c5", owner: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495",…}
components: {0: {x: -0.4637117156600495, y: 2.255, z: 8.3544556410586}, 1: {x: 0, y: -14.000000000000009, z: 0},…}
0: {x: -0.4637117156600495, y: 2.255, z: 8.3544556410586}
1: {x: 0, y: -14.000000000000009, z: 0}
2: {x: 1, y: 1, z: 1}
3: {,…}
4: {left_hand_pose: 0, right_hand_pose: 0}
5: {x: 0, y: 1.6, z: 0}
6: {x: 0, y: 0, z: 0}
7: {x: 0, y: 0, z: 0}
8: {x: 0, y: 0, z: 0}
9: false
10: {x: 0, y: 0, z: 0}
11: {x: 0, y: 0, z: 0}
12: false
creator: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495"
isFirstSync: true
lastOwnerTime: 1593446133299
networkId: "mi2p4c5"
owner: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495"
parent: null
persistent: false
template: "#remote-avatar"
dataType: "u"

and yet another example:

[null, "235", "phoenix", "heartbeat", {}]
0: null
1: "235"
2: "phoenix"
3: "heartbeat"
4: {}

and the one I actually need:

[null, null, "room:zRAMDON", "message", {session_id: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495",…}]
0: null
1: null
2: "room:zRAMDON"
3: "message"
4: {session_id: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495",…}
body: "testtttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt"
session_id: "fa477e9d-7e92-4c1d-9b7b-6e9e0e975495"
type: "chat"

so is clear there is a json array of 5 elements the problem is after element 3. I have try to parse all this into a auto json to go struct tool and even the tool gets confused and spits errors..

ok so I am not sure what im doing but I have combined 3 diff json outputs into one like:

type WebSocketHubs []WebSocketHubElement

type WebSocketHubClass struct {
    SessionID string `json:"session_id"`
    Body      string `json:"body"`
    Type      string `json:"type"`
    DataType  string `json:"dataType"`
    Data      Data   `json:"data"`
}

type WebSocketHubElement struct {
    String            *string
    WebSocketHubClass *WebSocketHubClass
}

type Data struct {
    NetworkID     string                     `json:"networkId"`
    Owner         string                     `json:"owner"`
    Creator       string                     `json:"creator"`
    LastOwnerTime int64                      `json:"lastOwnerTime"`
    Template      string                     `json:"template"`
    Persistent    bool                       `json:"persistent"`
    Parent        interface{}                `json:"parent"`
    Components    map[string]*ComponentValue `json:"components"`
    IsFirstSync   bool                       `json:"isFirstSync"`
}

type ComponentClass struct {
    X             *float64 `json:"x,omitempty"`
    Y             *float64 `json:"y,omitempty"`
    Z             *float64 `json:"z,omitempty"`
    AvatarSrc     *string  `json:"avatarSrc,omitempty"`
    AvatarType    *string  `json:"avatarType,omitempty"`
    Muted         *bool    `json:"muted,omitempty"`
    LeftHandPose  *int64   `json:"left_hand_pose,omitempty"`
    RightHandPose *int64   `json:"right_hand_pose,omitempty"`
}

type ComponentValue struct {
    Bool           *bool
    ComponentClass *ComponentClass
}

but now I get:

Error read: json: cannot unmarshal string into Go value of type main.WebSocketHubClass

:(


Solution

  • ok so I got tired of no help and no clear documentation and just did the brutebruce approach and used the call to array and maps, and then compare strings to get what I needed.

          var leerCHAT []interface{}
    
        for {
            //line, message, err := ws.ReadMessage()
            err := ws.ReadJSON(&leerCHAT)
    
            if err != nil {
                log.Printf("Error read: %s", err)
                break
            }
            log.Printf("Message received: %v", leerCHAT[2])
            if leerCHAT[3] == "message" {
                //var cookie string
                cookie := leerCHAT[4].(map[string]interface{})
                log.Printf("el chat dice: %s", cookie["body"].(string))
                chatMSG := cookie["body"].(string)
                go MatrixSay(matrixClient, chatMSG, matrixChannel)
    
            }
    
        }
    

    I changed this with the help of another question, that I had another issue but ended up refactoring the whole thing. Whats the best way to get content from a generic and somehow dynamic go map?