问题
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-catchblock
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 getnilas 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