[英]Swift 4 JSON Decoder
我知道其他問題已經解決了這個問題,但是我已經關注了這些問題,但仍然感到困惑。 這是我的JSON結構:
{
"FindBoatResult": {
"num_boats": 10,
"boat": [
{
"num_segments": 1,
"segments": [
{
"ident": "String",
"origin" : {
"code" : "String"
},
},
]
}
等等...但這就是結構的深度。 每個JSON響應中都有多個“段”返回。 在Swift中,我有這段代碼。
struct Result : Decodable {
let FindBoatResult : FindBoatResult
}
struct FindBoatResult : Decodable {
let boats : Boats
let num_boats : Int
}
struct Boats : Decodable {
let segments : [Segments]
}
struct Segments : Decodable {
let ident : String?
let origin : Origin
}
struct Origin : Decodable {
let code : String
}
func getBoats() {
let urlString = "http://myApi"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let data = data else {return}
let dataAsString = String(data: data, encoding: .utf8)
//print(dataAsString)
do {
let boats = try
JSONDecoder().decode(FindBoatResult.self, from: data)
print(boats)
} catch {
print(err)
}
}.resume()
}
這會失敗並拋出err,但err會顯示為nil..so,所以我無法說出我所缺少的內容。 dataAsString按預期方式打印出JSON,因此我知道“數據”是好的。
我發現了幾個小問題。 嘗試替換此:
struct FindBoatResult: Decodable {
let boats: Boats
let num_boats: Int
}
struct Boats: Decodable {
let segments: [Segments]
}
有:
struct FindBoatResult: Decodable {
let boat: [Boat]
let num_boats: Int
}
struct Boat: Decodable {
let segments: [Segments]
}
最后,使用Result
類型(而不是FindBoatResult
)進行解碼:
JSONDecoder().decode(Result.self, from: data)
擴展Paulo的答案,我可能進一步建議,如果您堅持使用的鍵具有與屬性名稱不符合Swift約定的鍵,則可以使用CodingKeys
模式將JSON鍵轉換為更好的Swift屬性名稱,例如:
struct BoatResult: Decodable { // I'd simplify this name
let boatCollection: BoatCollection
enum CodingKeys: String, CodingKey {
case boatCollection = "FindBoatResult"
}
}
struct BoatCollection: Decodable { // I'd simplify this, too, removing "Find" from the name; verbs are for methods, not properties
let boats: [Boat]
let numberOfBoats: Int
enum CodingKeys: String, CodingKey {
case boats = "boat" // "boat" isn't great property name for an array of boats, so let's map the poor JSON key to better Swift name here
case numberOfBoats = "num_boats" // likewise, let's map the "_" name with better camelCase property name
}
}
struct Boat: Decodable { // This entity represents a single boat, so let's use "Boat", not "Boats"
let segments: [Segment]
}
struct Segment: Decodable { // This entity represents a single segment, so let's use "Segment", not "Segments"
let identifier: String
let origin: Origin
enum CodingKeys: String, CodingKey {
case identifier = "ident" // `ident` isn't a common name for identifier, so let's use something more logical
case origin
}
}
struct Origin: Decodable {
let code: String
}
因此,例如,使用多個(如boats
),當你代表對象的數組,並使用CodingKeys
的誤導映射boat
JSON關鍵,這更好的命名boats
數組引用。 或者,當您擁有num_boats
類的鍵時,您不必感覺自己必須在Swift屬性中使用該壞名,而不必使用諸如numberOfBoats
(或count
或其他任何東西)之類的更好的名稱,而不必使用_
語法,這是非常不明智的。
顯然,如果您控制着JSON的設計,則可以在那里修復一些選擇不佳的鍵名,但是即使您決定要Web服務使用_
語法,也可以繼續使用CodingKeys
確保您的Swift對象遵守camelCase約定。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.