问题描述
我正在,因为焦点已更改.
I'm carrying this on from this question, since the focus has changed.
我正在尝试通过websocket从蒸气服务器发送字符串数据.客户端是主要问题所在.该代码成功接收了字符串,该字符串应为JSON(但不能绝对保证-超出范围).
I am trying to send string data from a vapor server over a websocket. The client side is where the main question is. This code successfully receives the string, which is expected to be JSON (but not absolutely guaranteed -- out of scope).
switch message { case .data(let data): print("data: \(data)") case .string(let str): // let data = str.message(using: .utf8) let jsonData = Data(str.utf8) print("string: \(jsonData)") do { struct Person : Codable { var name: String } let decoder = JSONDecoder() let people = try decoder.decode([Person].self, from: jsonData) print("result: \(people)") } catch { print(error.localizedDescription) } }
在获得一些非常有用的指导后,发送诸如"{\"name\": \"Bobberoo\"}"之类的字符串会打印出
After some very helpful guidance, sending a string such as "{\"name\": \"Bobberoo\"}" will print out
string: 20 bytes The data couldn’t be read because it isn’t in the correct format.
如果我将其包裹在括号中,则"[{\"name\": \"Bobberoo\"}]"会产生更有用但对我来说仍然是神秘的输出:
If I wrap it in braces "[{\"name\": \"Bobberoo\"}]" produces the more helpful but still mystifing (to me) output:
result: [wb2_socket_client.WebSocketController.(unknown context at $101a35028).(unknown context at $101a350c0).(unknown context at $101a35158).Person(name: "Bobberoo")]
很明显,解码正在发生,但是它包装在这些上下文中.这些是什么?我可以看到,第一个是WebSocketController的实例.我该如何访问这些数据.
Clearly, the decoding is happening, but it's wrapped in these contexts. What are they? I can see that the first is the instance of the WebSocketController. How do I access this data.
并且不具煽动性:在任何数量的上下文中,管理JSON都是微不足道的操作. Python/Flask,Node,Ruby/Rails等我已经使用了所有这些,实现这种交互是微不足道的.在Swift中,这是一场可怕的,文档不足的噩梦.至少,这是我的经验.为什么?我知道该语言是类型安全的,但这很荒谬.
And as a non-inflammatory aside: managing JSON is a trivial operation in any number of contexts. Python/Flask, Node, Ruby/Rails and on and on; I've used all these and implementing this kind of interaction is trivial. In Swift, it's a horrible, underdocumented nightmare. At least, that's my experience. Why? I know the language is type safe, but this is ridiculous.
推荐答案
error.localizedDescription不会给您错误消息,该消息对于调试非常有用.另一方面,如果您直接打印error:
error.localizedDescription won't give you an error message that is useful message for debugging. On the other hand, if you print error directly:
print(error)
您会得到一些类似期望解码数组但找到字典"的字样,这正是在
You'd get something along the lines of "expected to decode array but found dictionary instead", which is exactly what is happening in the case of
{ "name": "Bobberoo" }
您正在解码[Person].self,即的数组,但是您的JSON根不是JSON数组.如果您这样做的话,上面的JSON可以被解码:
You are decoding a [Person].self, i.e. an array of Person, but your JSON root is not a JSON array. The above JSON can be decoded if you did:
let people = try decoder.decode(Person.self, from: jsonData)
这是类型的默认字符串表示形式.您的Person结构不符合CustomStringConvertible或CustomDebugStringConvertible或TextOutputStreamable,因此"Swift标准库会自动提供未指定的结果" (链接指向String.init(reflecting:),大概是在print数组Person的途中被调用的地方)并用作字符串表示形式.
This is the default string representation of a type. Your Person struct does not conform to CustomStringConvertible or CustomDebugStringConvertible or TextOutputStreamable, so "an unspecified result is supplied automatically by the Swift standard library" (the link points to String.init(reflecting:), which presumably gets called somewhere along the way when you print the array of Person) and used as the string representation.
从我所看到的,它的当前实现是struct的完全限定名称-从模块开始,然后是顶级类,然后是每个封闭的作用域,以struct名称结尾,然后是struct中的成员括号.事实证明,包围范围没有名称",因此仅称为(unknown context at xxxxx).这都是非常多的实现细节,是您不关心的事情.
From what I can see, its current implementation is the fully qualified name of the struct - starting with the module, then the top-level class, then each enclosing scope, ending with the struct name, followed by the struct's members in brackets. It turns out that the enclosing scopes has no "names", and so are just called (unknown context at xxxxx). This is all very much implementation details, and things that you shouldn't care about.
您应该做的是提供CustomStringConvertible的实现:
What you should do, is provide an implementation of CustomStringConvertible:
struct Person: CustomStringConvertible { ... var description: String { "name: \(name)" } }
现在打印people给出:
[name: Bobberoo]
不. WebSocketController是Person结构的完全限定名称的一部分.正如您所期望的,解码数组中恰好有一个实例,它是Person的实例!
No. The WebSocketController is part of the fully qualified name of your Person struct. There is exactly one instance in your decoded array, and it's an instance of Person, as you would expect!
要访问其名称,请执行以下操作:
To access its name:
if let firstPerson = people.first { let firstPersonsName = firstPerson.name }
这篇关于在Swift中接收Websocket数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!