[英]How to Decode selected keys manually and rest with the automatic decoding with swift Decodable?
這是我正在使用的代碼,
struct CreatePostResponseModel : Codable{
var transcodeId:String?
var id:String = ""
enum TopLevelCodingKeys: String, CodingKey {
case _transcode = "_transcode"
case _transcoder = "_transcoder"
}
enum CodingKeys:String, CodingKey{
case id = "_id"
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TopLevelCodingKeys.self)
if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcode) {
self.transcodeId = transcodeId
}else if let transcodeId = try container.decodeIfPresent(String.self, forKey: ._transcoder) {
self.transcodeId = transcodeId
}
}
}
這里, transcodeId
由_transcode
或_transcoder
決定。 但我希望自動解碼id
和其余鍵(不包括在此處)。 我該怎么做 ?
在Codable
類型中實現init(from:)
,您需要手動解析所有鍵。
struct CreatePostResponseModel: Decodable {
var transcodeId: String?
var id: String
enum CodingKeys:String, CodingKey{
case id, transcode, transcoder
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decodeIfPresent(String.self, forKey: .id) ?? ""
if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcode) {
self.transcodeId = transcodeId
} else if let transcodeId = try container.decodeIfPresent(String.self, forKey: .transcoder) {
self.transcodeId = transcodeId
}
}
}
在上面的代碼中,
Codable
。 使用Decodable
就足夠了。CodingKey
使用多個enums
。 您可以使用單個enum CodingKeys
。rawValue
是的case
在enum CodingKeys
。 因此, TopLevelCodingKeys
不需要"_transcode"
和"_transcoder"
rawValues
。 除此之外,您可以使用keyDecodingStrategy
作為.convertFromSnakeCase
來處理下划線符號(蛇大小寫符號),即
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase //here.....
let model = try decoder.decode(CreatePostResponseModel.self, from: data)
print(model)
} catch {
print(error)
}
因此,您不需要顯式處理所有蛇形大小寫的鍵。 它將由JSONDecoder
自行處理。
無論您在何處都可以為一個變量添加多個鍵,這對您來說都是不錯的解決方案之一:
var transcodeId:String?
public init(from decoder: Decoder) throws {
do {
let container = try decoder.container(keyedBy: CodingKeys.self)
transcodeId = container.getValueFromAvailableKey(codingKeys: [CodingKeys._transcoder,CodingKeys._transcode])
} catch {
print("Error reading config file: \(error.localizedDescription)")
}
}
extension KeyedDecodingContainerProtocol{
func getValueFromAvailableKey(codingKeys:[CodingKey])-> String?{
for key in codingKeys{
for keyPath in self.allKeys{
if key.stringValue == keyPath.stringValue{
do{
return try self.decodeIfPresent(String.self, forKey: keyPath)
} catch {
return nil
}
}
}
}
return nil
}
}
希望能幫助到你。
編譯器生成的init(from:)
是全有或全無。 您不能讓它解碼某些鍵並“手動”解碼其他鍵。
使用編譯器生成的init(from:)
一種方法是為您的struct
兩個可能的編碼屬性,並使transcodeId
成為計算屬性:
struct CreatePostResponseModel: Codable {
var transcodeId: String? {
get { _transcode ?? _transcoder }
set { _transcode = newValue; _transcoder = nil }
}
var _transcode: String? = nil
var _transcoder: String? = nil
var id: String = “”
// other properties
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.