Har*_*ngk 21 rest json optional ios swift
我的iOS应用程序有一个非常常见的设置:它向使用JSON对象响应的API服务器进行HTTP查询.然后将这些JSON对象解析为适当的Swift对象.
最初,我将属性划分为必需的属性和可选属性,主要基于我的API服务器的数据库要求.例如id
,email
和name
如此他们使用非可选类型需要的字段.其他人可以NULL
在数据库中,因此它们是可选类型.
class User {
let id: Int
let email: String
let profile: String?
let name: String
let motive: String?
let address: String?
let profilePhotoUrl: String?
}
Run Code Online (Sandbox Code Playgroud)
最近,我开始怀疑这是否是一个很好的设置.我发现尽管某些属性可能总是在数据库中,但这并不意味着这些属性将始终包含在JSON响应中.
例如,在"用户配置文件"页面中,需要所有这些字段才能正确显示视图.因此,JSON响应将包括所有这些字段.但是,对于列出用户名称的视图,我不需要email
或者id
,JSON响应也可能不包括这些属性.不幸的是,这将导致错误和解析JSON响应到斯威夫特对象时,因为应用程序崩溃预计的应用id
,email
,name
是永远不会比零.
我正在考虑将Swift对象的所有属性更改为可选对象,但感觉就像丢掉了这种特定于语言的功能的所有好处.此外,我将不得不编写更多代码行来打开应用程序中其他地方的所有这些选项.
另一方面,JSON对象本质上不能与Swift的严格静态类型和nil检查非常互操作,所以最好简单地接受这种烦恼.
我应该过渡到每个属性作为选项的模型吗?或者,还有更好的方法?我很感激这里有任何评论.
首先要问的是:"列出用户名称的视图"的元素是否需要与"用户个人资料页面"后面的模型对象是同一类型的对象?也许不是.也许你应该专门为用户列表创建一个模型:
struct UserList: Decodable {
struct Item: Decodable {
var id: Int
var name: String
}
var items: [Item]
}
Run Code Online (Sandbox Code Playgroud)
(虽然问题说JSON响应可能不包括id
,但它似乎不是没有id的用户列表特别有用,所以我在这里需要它.)
如果你真的希望它们是同一种对象,那么你可能希望将用户建模为具有服务器始终发送的核心属性,以及可能为零的"详细信息"字段:
class User: Decodable {
let id: Int
let name: String
let details: Details?
struct Details: Decodable {
var email: String
var profile: String?
var motive: String?
var address: String?
var profilePhotoUrl: String?
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
details = container.contains(.email) ? try Details(from: decoder) : nil
}
enum CodingKeys: String, CodingKey {
case id
case name
case email // Used to detect presence of Details
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我创建了Details
,如果它存在,使用Details(from: decoder)
,而不是通常container.decode(Details.self, forKey: .details)
.我这样做是Details(from: decoder)
为了使得属性Details
来自与JSON对象相同的属性User
,而不是需要嵌套对象.
前提:
部分表示是 REST 中的常见模式。这是否意味着 Swift 中的所有属性都需要是可选项?例如,客户端可能只需要一个视图的用户 ID 列表。这是否意味着所有其他属性(姓名、电子邮件等)都需要标记为可选?这是 Swift 的好习惯吗?
模型中可选的标记属性仅表示密钥可能会或可能不会出现。它允许读者在第一眼中了解有关模型的某些信息。
如果您只为不同的 API 响应结构维护一个通用模型,并且将所有属性都设为可选,那么这是否是好的做法是很有争议的。
我已经这样做了,它咬人。有时很好,有时只是不够清楚。
为多个 API 保留一个模型就像设计一个ViewController
具有许多 UI 元素的模型,并根据特定情况确定应显示或不显示哪些 UI 元素。
这增加了新开发人员的学习曲线,因为需要更多地了解系统。
假设我们继续使用 Swift 的Codable
编码/解码模型,我会将其分解为单独的模型,而不是维护具有所有可选和/或默认值的通用模型。
我的决定的原因是:
分离度
考虑稍后可能会出现的特定于 API 的附加密钥。
但是,如果我很懒惰并且我强烈感觉疯狂的变化不会出现,我会继续制作所有键可选并承担相关成本。
归档时间: |
|
查看次数: |
1579 次 |
最近记录: |