问题
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 getnil
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