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



新的 Swift "Decoder" 类听起来像是解析 JSON 数据的好方法,但我发现的所有示例都使用了一个众所周知的、定义明确的"结构"来做到这一点。

就我而言,我正在查询一个返回巨大 JSON 字符串的任意网站,我只关心一些(深度嵌套的(字段,所以我不想花那么多时间来定义一个"结构"来获取它们。

甚至可以用"解码器"做到这一点吗? 如果是这样,该怎么做?

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

  • 无需为您不关心的"字段"定义结构属性。如果 JSON 字典包含 100 个键,而相应的结构只包含一个属性,没问题;将获取该密钥,而不会获取其他密钥。

  • 关于"深度嵌套"部分,编写简单的嵌套结构应该不会花费太多时间,这些结构执行潜水以到达您真正关心的字典。但是,如果您甚至不想这样做,则可以编写一个向下潜入并获取所需值的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:)的实现,就像这样(这可能看起来很多工作,但事实并非如此,因为AnyCodingKey实现是样板的,从这里复制和粘贴,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键,也不需要创建结构嵌套。

当然你可以做到这一点,但是使用JSonSerializationDecodable,你必须序列化json,直到到达所需的内容然后解码它,但相反,我建议只为根键创建结构然后解码,把它想象成从上到下的路径 不要解码不在所需内容路径中的键

最新更新