How Do I Send a Dictionary to a Client using Vapor Websockets

纵然是瞬间 提交于 2021-02-10 19:51:27

问题


I've continued this question here, because the focus has changed, but is related.

Vapor is communicating between a server and and iOS client. Just setup code, for learning purposes.

Now, I want to send a dictionary of values via the established connection using JSON. I'm getting caught up in the unexplained logic of demo code, but here's where I am, in my vapor routes:

    app.webSocket("respond") { req, ws in
        ws.onText { ws, text in
            print(text)
        
            let msgDict = "{'name' = 'bobby'}"
            let encoder = JSONEncoder()
            let data = try encoder.encode(msgDict)
                
            ws.send(data)
        }
    }

This won't compile: Invalid conversion from throwing function of type '(WebSocket, String) throws -> ()' to non-throwing function type '(WebSocket, String) -> ()'

while I generally understand this error, and dependent on how I play with this it varies.

What generally I'm looking for is a simple pattern to take internal dictionary values, encode them into JSON, and send them. What am I not doing, or not doing right?


回答1:


I see two problems with that code.

The first one, explained by the compiling error, it's actually telling that it will not handle any errors thrown. When you do encoder.encode(msgDict), this code can throw an Error, and you're not handling this possible error anywhere. If you handle that possible error, code you wrote in that closure will have the expected type. You have a few options to do so:

  • Wrap the code around a do-catch block
do {
    let data = try encoder.encode(msgDict)
    ws.send(data)
} catch let error {
    // Handle error
}
  • Use try?, means you do not handle the error but get nil as a result, if an error occurred.
if let data = try? encoder.encode(msgDict) {
    ws.send(data)
}
  • Use try!, means you force-unwrap the result (not advisable, but you can try, if you're 100% sure)
let data = try! encoder.encode(msgDict)
ws.send(data)

The second problem is how you're writing that response - "{'name' = 'bobby'}". This is an invalid JSON, you should use double quotes instead:

let msgDict = "{\"name\" = \"bobby\"}"

You can also use Dictionary, as long as the content is of type Encodable:

let msgDict = ["name": "bobby"]

You can also use JSONEncoder to encode any instances of classes that conform to Encodable.

So the whole thing, I'd write like this:

app.webSocket("respond") { req, ws in
    ws.onText { ws, text in
        print(text)
    
        let msgDict = ["name": "bobby"]
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(msgDict)
            ws.send(data)
        }
        catch let error {
            print("An error occurred: \(error)")
        }
    }
}



回答2:


The error tells you that a do - catch block is missing

do {
    let encoder = JSONEncoder()
    let data = try encoder.encode(msgDict)
    ws.send(data)
} catch { print(error) }

However your approach to create JSON cannot work because msgDict is neither valid JSON nor a Swift dictionary.

To encode the dictionary with JSONEncoder it must be a Swift dictionary

let msgDict = ["name":"bobby"]

But JSONEncoder is overkill. A simpler way is to create the JSON dictionary literally

app.webSocket("respond") { req, ws in
    ws.onText { ws, text in
        print(text)
    
        let msgDict = #"{"name":"bobby"}"#
        ws.send(Data(msgDict.utf8))
    }
}

            
        


来源:https://stackoverflow.com/questions/65988137/how-do-i-send-a-dictionary-to-a-client-using-vapor-websockets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!