在 Swift 中接收 Websocket 数据

2024-03-10

我继续这个从这个问题 https://stackoverflow.com/questions/65988137/how-do-i-send-a-dictionary-to-a-client-using-vapor-websockets/65988723?noredirect=1#comment116671377_65988723,因为焦点已经改变。

我正在尝试通过 Websocket 从 Vapor 服务器发送字符串数据。客户端是主要问题所在。此代码成功接收字符串,该字符串预计为 JSON(但不能绝对保证 - 超出范围)。

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\"}"将打印出

string: 20 bytes
The data couldn’t be read because it isn’t in the correct format.

如果我把它用大括号括起来"[{\"name\": \"Bobberoo\"}]"产生更有帮助但仍然令人困惑(对我来说)的输出:

result: [wb2_socket_client.WebSocketController.(unknown context at $101a35028).(unknown context at $101a350c0).(unknown context at $101a35158).Person(name: "Bobberoo")]

显然,解码正在发生,但它包含在这些上下文中。这些是什么?我可以看到第一个是 WebSocketController 的实例。我如何访问这些数据。

顺便说一句,这不是煽动性的:在任何情况下,管理 JSON 都是一项微不足道的操作。 Python/Flask、Node、Ruby/Rails 等等;我已经使用了所有这些并且实现这种交互是微不足道的。在 Swift 中,这是一个可怕的、缺乏记录的噩梦。至少,这是我的经验。为什么?我知道该语言是类型安全的,但这很荒谬。


error.localizedDescription不会给您一条对调试有用的错误消息。另一方面,如果您打印error直接地:

print(error)

你会得到类似“预期解码数组但找到字典”的内容,这正是在这种情况下发生的情况

{
    "name": "Bobberoo"
}

你正在解码一个[Person].self,即array of Person,但您的 JSON 根不是 JSON 数组。如果你这样做的话,上面的 JSON 就可以被解码:

let people = try decoder.decode(Person.self, from: jsonData)

显然,解码正在发生,但它包含在这些上下文中。这些是什么?

这是类型的默认字符串表示形式。你的Person结构不符合CustomStringConvertible or CustomDebugStringConvertible or TextOutputStreamable, so “Swift 标准库自动提供未指定的结果” https://developer.apple.com/documentation/swift/string/1541282-init(链接指向String.init(reflecting:),当您在途中的某个地方可能会调用它print的数组Person) 并用作字符串表示形式。

据我所知,它当前的实现是结构体的完全限定名称 - 从模块开始,然后是顶级类,然后是每个封闭范围,以结构体名称结尾,后面是括号中的结构体成员。事实证明,封闭的范围没有“名称”,因此只是被称为(unknown context at xxxxx)。这都是非常多的实现细节,以及您不应该关心的事情。

你应该做的是提供一个实现CustomStringConvertible:

struct Person: CustomStringConvertible {
    ...

    var description: String { "name: \(name)" }
}

正在打印people gives:

[name: Bobberoo]

我可以看到第一个是WebSocketController.

No. The WebSocketController是您的完全限定名称的一部分Person结构。解码后的数组中只有一个实例,它是Person,如您所料!

我如何访问这些数据?

要访问其名称:

if let firstPerson = people.first {
    let firstPersonsName = firstPerson.name
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Swift 中接收 Websocket 数据 的相关文章

随机推荐

  • 尝试复制大文件时出现 NIO 错误

    我有将文件复制到另一个位置的代码 public static void copyFile String sourceDest String newDest throws IOException File sourceFile new Fil
  • 如何获取终端结果并设置 JTextArea 来读取终端?

    我最近完成了一个 GUI 用户可以在其中输入标准 并获得符合所述条件的结果 该程序的工作结果明智 但我无法让我的 GUI 中的文本字段读取我的终端窗口结果 我的 GUI 代码如下 package project205 import java
  • iOS 静默推送通知仅在连接到 xcode 时有效

    我有一个奇怪的问题 我最近将 Xcode 更新到 6 1 1 以对我之前使用 Xcode 5 发布的应用程序进行更改 运行良好 现在 由于某种原因 当我使用新的 Xcode 测试后台静默推送通知时 它只有在我的 iPhone 连接到 Mac
  • 在 Dart 中合并两个对象列表

    我有具有参数名称和参数计数器的对象 这些对象存储在列表中 我的列表中的某些项目具有重复的参数 名称 我想删除列表内的重复项 并将该重复项的计数器添加到重复对象参数中 class Person Person this name this co
  • 对于大输入返回负数的阶乘函数

    我的阶乘函数似乎适用于 1 到 6 之间的数字 但不适用于大于 6 的数字 例如从 21 开始 结果是否定的 我不明白为什么 这是我的功能 factorial Int gt Int factorial 0 1 factorial 1 1 f
  • Apache Flink 检查点卡住

    我们正在运行一个 ListState 介于 300GB 到 400GB 之间的作业 并且有时该列表可能会增加到数千 在我们的用例中 每个项目都必须有自己的 TTL 因此我们使用 S3 上的 RocksDB 后端为此 ListState 的每
  • for 循环后的 Python 语法错误(在解释器中)

    我正在从控制台运行一些 python 代码 粘贴 并得到意外的结果 代码如下所示 parentfound False structfound False instruct False wordlist fileHandle open con
  • 如何获取 ImageView 中 Drawable 的尺寸? [复制]

    这个问题在这里已经有答案了 检索 ImageView 中 Drawable 尺寸的最佳方法是什么 My ImageView有一个初始化方法 我在其中创建ImageView private void init coverImg new Ima
  • 在 C++ 中使用 new 创建引用

    我有以下代码 似乎用 new 创建引用是可以的 但是当用 new 创建对象时 当我尝试重新收集分配的内存时 它会崩溃 float f new float 1 3 delete f float f1 new float delete f1 我
  • “<-”是否意味着在Haskell中分配变量?

    刚开始Haskell 据说Haskell中除了IO包之外的所有东西都是 不可变的 那么当我将名称绑定到某个东西时 它总是不可变的 问题 如下 Prelude gt let removeLower x c c lt x c elem A Z
  • Web API 序列化从小写字母开始的属性

    如何配置要使用的 Web API 的序列化camelCase 从小写字母开始 属性名称而不是PascalCase就像 C 中一样 我可以在整个项目的全球范围内进行吗 如果您想更改 Newtonsoft Json 又名 JSON NET 中的
  • 为重复的索引值添加后缀

    这是一个 df 0 01 0 029064 0 01 0 032876 0 01 0 040795 0 02 0 027003 0 02 0 0315 需要将其与另一个框架连接 但出现错误 无法从重复轴重新索引 我想要的是这样的 df 0
  • vs2015不断添加project.lock.json到tfs

    我的文件夹结构是 解决方案文件夹 tfignore 文件 每个项目的文件夹 但 vs2015 继续将我的 project lock json 文件包含在源代码管理中 在我的 tfignore 文件中 我添加了 project lock js
  • C 中的 case 标签不会减少为整数常量?

    我正在开发一个游戏 我运行了我的代码并收到错误 case 标签不会减少为整数常量 我想我知道这意味着什么 但是我该如何解决它呢 这是我的代码 include
  • 如何将列表列表从宽变为长

    我有一个具有共同结构的列表列表 require data table l lt list a1 list b data table rnorm 3 c data table rnorm 3 d data table rnorm 3 a2 l
  • C++ 与 Python 精度

    尝试查找 num num 的前 k 位数字的问题我用 C 和 Python 编写了相同的程序 C long double intpart num f digit k cin gt gt num gt gt k f digit pow 10
  • 元组比较

    我有一本定义如下的字典 d date tuple date open tuple open close tuple close min tuple min max tuple max MA tuple ma 这些元组中的每一个都包含一个值列
  • 在 iOS 中实现 Google 自定义搜索 API

    我浏览了几个链接 以便找到在 ios 应用程序中实现 google customsearchapi 的正确步骤 并在此过程中花费了大约 6 7 个小时 Links https developers google com custom sea
  • 模型的 flow_from_directory 拟合产生 ValueError:输入 0 与图层模型不兼容

    我有以下模型 我尝试使用 ImageDataGenerator 与 flow from directory 和 fit generator 来拟合模型 但是出现以下错误 ValueError Input 0 is incompatible
  • 在 Swift 中接收 Websocket 数据

    我继续这个从这个问题 https stackoverflow com questions 65988137 how do i send a dictionary to a client using vapor websockets 6598