我想知道是否有一種方法可以將 JSON 解碼為結構體,當發送 JSON 的 API 可能與其輸入不一致時。在這種情況下,它有時將屬性作為陣列發送,有時作為字串發送。我不確定如何處理,或者是否有使用 Decodable 的好方法。下面舉例。我的結構:
struct Movie: Decodable {
let title: String
let cast: [String]
let director: [String]
}
JSON:
[{
"title": "Pulp Fiction",
"cast": [
"John Travolta",
"Uma Thurman",
"Samuel L. Jackson"
],
"director": "Quentin Tarantino"
},
{
"title": "Spider-Man: Into the Spider-Verse",
"cast": [
"John Travolta",
"Uma Thurman",
"Samuel L. Jackson"
],
"director": [
"Bob Persichetti",
"Peter Ramsey",
"Rodney Rothman"
]
}]
我能夠毫無問題地解碼蜘蛛俠,但如果只有一個導演,它會以字串而不是陣列的形式出現。有沒有辦法為此使用 Decodable?我知道我可以手動構建結構,但最好不要這樣做。不幸的是,我無法控制這里的 API。提前致謝。
uj5u.com熱心網友回復:
解碼不同型別的最通用方法是具有關聯值的列舉。
但是在這種型別非常相關的情況下,您也可以撰寫自定義初始化程式,結構成員以復數形式命名并宣告為陣列
struct Movie: Decodable {
let title: String
let cast: [String]
let directors: [String]
private enum CodingKeys : String, CodingKey { case title, cast, director }
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.title = try container.decode(String.self, forKey: .title)
self.cast = try container.decode([String].self, forKey: .cast)
if let singleDirector = try? container.decode(String.self, forKey: .director) {
self.directors = [singleDirector]
} else {
self.directors = try container.decode([String].self, forKey: .director)
}
}
}
uj5u.com熱心網友回復:
struct Movie: Codable {
let title: String
let cast: [String]
let director: Director
}
enum Director: Codable {
case string(String)
case stringArray([String])
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode([String].self) {
self = .stringArray(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Director.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Director"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .string(let x):
try container.encode(x)
case .stringArray(let x):
try container.encode(x)
}
}
}
typealias Movies = [Movie]
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/355017.html