sur*_*der 7 json decoder ios swift codable
默认情况下,Decodable协议将JSON值转换为对象值而不进行任何更改.但有时您需要在json解码期间转换值,例如,在JSON中,{id = "id10"}但是在您的类实例中,您需要将数字10放入属性id(或者使用不同名称的偶数属性).
您可以init(from:)使用任何值实现可以执行所需操作的方法,例如:
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
latitude = try container.decode(Double.self, forKey:.latitude)
longitude = try container.decode(Double.self, forKey: .longitude)
// and for example there i can transform string "id10" to number 10
// and put it into desired field
}
Run Code Online (Sandbox Code Playgroud)
这听起来对我来说很棒,但是如果我只想为其中一个 JSON字段更改值并将所有其他20个字段保留为没有变化,该怎么办?如果init(from:)我应该手动获取并为我班级的20个字段中的每个字段添加值!经过多年的objC编码,我直接调用super的实现,init(from:)然后对某些字段进行更改,但是如何使用Swift和Decodable协议实现这样的效果呢?
您可以使用一个lazy var. 缺点是您仍然必须提供键列表,并且不能将模型声明为常量:
struct MyModel: Decodable {
lazy var id: Int = {
return Int(_id.replacingOccurrences(of: "id", with: ""))!
}()
private var _id: String
var latitude: CGFloat
var longitude: CGFloat
enum CodingKeys: String, CodingKey {
case latitude, longitude
case _id = "id"
}
}
Run Code Online (Sandbox Code Playgroud)
例子:
let json = """
{
"id": "id10",
"latitude": 1,
"longitude": 1
}
""".data(using: .utf8)!
// Can't use a `let` here
var m = try JSONDecoder().decode(MyModel.self, from: json)
print(m.id)
Run Code Online (Sandbox Code Playgroud)
目前,如果您想更改单个属性的解析,则必须完全实现encode和方法。decode
Swift Codable 的某些未来版本可能会允许逐案处理每个属性的编码和解码。但 Swift 功能的工作并不简单,而且还没有被优先考虑:
无论如何,我们的目标可能是提供一个强类型的解决方案,使您能够根据具体情况执行此操作,而不会掉入“悬崖”,必须实现所有属性
encode(to:并init(from:为了一个属性的利益而实施;该解决方案可能并不简单,需要进行大量 API 讨论才能弄清楚如何做得好,这就是为什么我们还无法做到这一点。- Itai Ferber,Swift 4 Codable 首席开发人员
https://bugs.swift.org/browse/SR-5249?focusedCommentId=32638
| 归档时间: |
|
| 查看次数: |
1689 次 |
| 最近记录: |