簡體   English   中英

Swift 可解碼:如何在解碼過程中轉換其中一個值?

[英]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)

當前,如果您想要更改甚至單個屬性的解析,則必須完全實現encodedecode方法。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM