[英]Swift Decodable: how to transform one of values during decoding?
默認情況下, Decodable
協議將 JSON 值轉換為 object 值,沒有任何變化。 但有時您需要在 json 解碼期間轉換值,例如,在 JSON 中您得到{id = "id10"}
但在您的 class 實例中您需要將數字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
}
這對我來說聽起來不錯,但如果我只想更改 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"
}
}
例:
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)
當前,如果您想要更改甚至單個屬性的解析,則必須完全實現encode
和decode
方法。
Swift Codable 的某些未來版本可能會允許逐個處理每個屬性的編碼和解碼。 但是 Swift 功能工作非常重要,尚未確定優先級:
無論如何,我們的目標是可能提供一種強類型的解決方案,允許您根據具體情況執行此操作,而不會掉下“懸崖”而不得不實施所有
encode(to:
和init(from:
為了一個財產的利益;解決方案可能很重要,需要大量 API 討論才能弄清楚如何做好,因此我們還不能做到這一點。- Itai Ferber,Swift 4 Codable 的首席開發人員
https://bugs.swift.org/browse/SR-5249?focusedCommentId=32638
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.