JSONDecoder-Keypath

CircleCI Isues License Swift Package Manager Cocoapods

为 Foundation.JSONDecoder 添加嵌套键路径支持

原理

在撰写本文时,我发现大多数流行的框架(主要是网络封装器)在处理键路径时做了一些糟糕的事情。

因此,假设我们有一个 Decodable (Codable) 对象,但在 API 响应中,我们是在某个自定义路径下获取它。大多数解决方案已经有通过键路径提取对象的接口,并且还添加了 Codable 支持。但问题是,在我看到的所有案例中,几乎所有实现都是这样的:

  1. 使用 JSONSerializationData 中提取 [String: Any]
  2. 在此字典中遵循键路径
  3. 将给定对象转换为 Data
  4. 使用 JSONDecoder 解析对象

显而易见,数据的来回转换是对资源的额外浪费。此外,对于大量数据,这是非常不可取的。

此软件包消除了前 3 个步骤。

用法

假设你有一个 Item 模型

struct Item: Codable {
 ...
}

我们有以下 JSON

{
 "foo" : <actual object>
}

要解析它,你需要这样写

let jsonData: Data = ...
let item = try decoder.decode(Item.self, from: jsonData, keyPath: "foo")

也支持嵌套键路径

let item = try decoder.decode(Item.self, from: jsonData, keyPath: "foo.bar")

键路径分隔符可以配置

let item = try decoder.decode(Item.self, from: jsonData, keyPath: "foo/bar", keyPathSeparator: "/")

底层原理

软件包向 JSONDecoder 添加了新方法

func decode<T>(_ type: T.Type,
                   from data: Data,
                   keyPath: String,
                   keyPathSeparator separator: String = ".") throws -> T where T : Decodable

在这个调用中,keypath 存储在 JSONDecoder.userInfo 中,然后使用私有类 KeyPathWrapper<T> 作为类型参数调用标准的 decode 方法。在 KeyPathWrapper 构造函数中,从 userInfo 中获取键路径数据,并使用这些值遍历解码器。之后,原始类型被解码。

安装

Swift Package Manager

.Package(url: "https://github.com/0111b/JSONDecoder-Keypath.git") 行添加到你的 Package.swift

Cocoapods

    pod 'JSONDecoder-Keypath'

结论

这基本上是自定义对象编码的幼稚实现,只花了我几个小时。但它表明我们必须思考如何使用提供的 API,并且不要懒于查看底层原理

计划与改进