ios - 如何使用 Swift 的 Decodable 来解析您只知道或只关心几个字段的任意 JSON 字符串?

标签 ios json swift

新的 Swift“Decoder”类听起来像是解析 JSON 数据的好方法,但我发现的所有示例都使用众所周知的、定义良好的“结构”来执行此操作。

就我而言,我正在查询一个返回巨大 JSON 字符串的任意网站,并且我只关心一些(深层嵌套)字段,因此我不想花所有时间来定义“结构” ' 来获取它们。

是否可以使用“解码器”来做到这一点?如果是这样,该怎么做呢?

最佳答案

这个问题似乎是基于对 Decodable 工作原理的误解。为了方便起见,Decodable 愿意在幕后进行一些自动代码生成,以便您可以定义一个结构体或结构体嵌套并解码整个 JSON。但您并不需要利用这一点来解码 JSON。

  • 无需为您不关心的“字段”定义结构体属性。如果 JSON 字典包含 100 个键,并且相应的结构只包含一个属性,那么没问题;将获取该 key ,而不获取其他 key 。

  • 关于“深度嵌套”部分,您应该不会花太多时间编写简单的嵌套结构来执行潜水以到达您真正关心的字典。但如果您甚至不想这样做,您可以编写一个 init(from:) 的实现,它会深入并获取所需的值。

换句话说,如果您认为 Decodable 主要由 init(from:) 的实现组成,并学习编写它所需的代码,那么您将看到这个 JSON 可以通过几行简单的快速代码进行解析。

举个例子,下面是一个深度嵌套信息的 JSON 草图,其中每个级别都有一堆我们想要忽略的额外信息:

{
  "ignore": true,
  "outer1": {
    "ignore": true,
    "outer2": {
      "ignore": true,
      "outer3": {
        "name": "matt",
        "ignore": true
      }
    }
  }
}

我想做的是定义一个非常简单的结构体 Person,它仅由深度嵌套的 name 组成:

struct Person : Decodable {
    let name : String
}

我能做到!为此,我自己实现了 Decodable,提供了一个“hoover”CodingKey 采用者结构和 init(from:) 的实现,如下所示(这可能看起来需要大量工作,但事实并非如此) t,因为 AnyCodingKey 实现是样板文件,从 here 复制并粘贴,并且 init(coder:) 实现只是几行易于编写的代码):

    struct Person : Decodable {
        let name : String
        struct AnyCodingKey : CodingKey {
            var stringValue: String
            var intValue: Int?
            init(_ codingKey: CodingKey) {
                self.stringValue = codingKey.stringValue
                self.intValue = codingKey.intValue
            }
            init(stringValue: String) {
                self.stringValue = stringValue
                self.intValue = nil
            }
            init(intValue: Int) {
                self.stringValue = String(intValue)
                self.intValue = intValue
            }
        }
        init(from decoder: Decoder) throws {
            var con = try! decoder.container(keyedBy: AnyCodingKey.self)
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer1"))
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer2"))
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer3"))
            let name = try! con.decode(String.self, forKey: AnyCodingKey(stringValue:"name"))
            self.name = name
        }
    }

当我想深入研究 JSON 并获取 name 信息时,这很简单:

let person = try! JSONDecoder().decode(Person.self, from: json)

结果是一个具有 name“matt” 的 Person 对象。请注意,我不必添加任何 ignore 键,也不需要嵌套结构。

关于ios - 如何使用 Swift 的 Decodable 来解析您只知道或只关心几个字段的任意 JSON 字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50897199/

相关文章:

objective-c - 由于未捕获的异常 'NSGenericException' 而终止应用程序,原因 : '*** Collection <__NSArrayM: 0x138cb4d0> was mutated while being enumerated

ios - JSQMessagesViewController 点击消息 Action

ios - 冗余图像加载到 tableview 单元格 swift

php - json_encode 不适用于加密字符串

android - 从 Flutter 的方法 channel 访问 Kotlin 中的参数数据

android - 如何从 URL 下载 JSON 对象数组,并为 Android 应用程序存储?

ios - 在基于 swift 的应用程序中播放 Avi 视频

ios - 在UITextView中以“语音气泡”样式显示消息的最佳方法-Swift

ios - Base64EncodedStringFromData Objective-C 的新 Swift 方式

iphone - 从 uiwebview 获取更新的 url