2017-09-21 66 views
0

我想實現Swift 4的新的可解碼協議,並有一些難以接近它。使用Swift 4的可解碼協議嵌套JSON服務器響應

這是我的JSON服務器響應:

{ 
    "success": true, 
    "errorCode": 0, 
    "message": "Succcess", 
    "data": { 
    "name": "Logan Howlett", 
    "nickname": "The Wolverine", 
    "image": "http://heroapps.co.il/employee-tests/ios/logan.jpg", 
    "dateOfBirth": 1880, 
    "powers": [ 
     "Adamantium Bones", 
     "Self-Healing", 
     "Adamantium Claws" 
    ], 
    "actorName": "Hugh Jackman", 
    "movies": [ 
     { 
     "name": "X-Men Origins: Wolverine", 
     "year": 2009 
     }, 
     { 
     "name": "The Wolverine", 
     "year": 2013 
     }, 
     { 
     "name": "X-Men: Days of Future Past", 
     "year": 2014 
     }, 
     { 
     "name": "Logan", 
     "year": 2017 
     }, 
    ] 
    } 
} 

什麼是解碼響應data部分的最佳方法? 另外,如果data突然變爲array而不是對象會發生什麼情況,我如何支持這兩種數據類型?

感謝很多:)

+0

'另外,如果數據突然變成一個數組而不是一個對象會發生什麼,我該如何支持這兩種數據類型? - 使用enum關聯你的類型值?一個用'array',另一個用'dictionary'。 – user28434

+0

您應該閱讀Codable文檔中的[Encoding and Decoding Custom Types](編碼和解碼自定義類型)(https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types),以瞭解如何編寫鏡像JSON表示的類型。大多數情況下,這涉及編寫類型並符合Codable,其餘部分應該爲您完成。 –

回答

0

首先你可以創建一個擴展爲一個幫手:

extension Data { 
    func decode <Generic: Codable>() -> Generic? { 
     let decoder = JSONDecoder() 
     let object = try? decoder.decode(Generic.self, from: self) 
     return object 
    } 
} 


extension Dictionary { 
    func decode <Generic: Codable>() -> Generic? { 
     let data = try? JSONSerialization.data(withJSONObject: self, 
               options: JSONSerialization.WritingOptions.prettyPrinted) 
     guard let d = data else { 
      return nil 
     } 
     return d.decode() 
    } 
} 

然後你就可以創建一個協議,以幫助你建立你的對象:

protocol Encode: Codable { 
    init(with dictionary: [String: Any]) 
    init(with data: Data) 
} 

默認執行:

extension Encode { 
    init(with data: Data) { 
     let object: Self? = data.decode() 
     guard let obj = object else { 
      fatalError("fail to init object with \(data)") 
     } 
     self = obj 
    } 

    init(with dictionary: [String: Any]) { 
     let object: Self? = dictionary.decode() 
     guard let obj = object else { 
      fatalError("fail to init object with \(dictionary)") 
     } 
     self = obj 
    } 

然後創建您的對象作爲符合y Codable協議的結構。它看起來像:

struct User: Codable { 
    var name: String? 
    var nickname: String? 
    ... 
    // If needed declare CodingKey here 
    // enum CodingKeys: String, CodingKey { 
    //  case date = "dateOfBirth" 
    //  ... 
    // } 
} 

struct Movies: Codable { 
    var name: String? 
    var year: Int? 
} 

現在你需要提取從你的迴應你的數據字典和應用新的初始化方法:

if let dic = json["data"] as? [String: Any] { 
    let user: User = User(with: dic) 
    // Do stuff here 
} 

如果數據突然變成一個數組,你將不得不處理它的方式不同(如本例中的用戶數組)

+0

請在評論中解釋爲什麼我的回答不合適,因此我可以替換或改進它。謝謝 –

+0

我不知道誰低估了你的答案,但它不是我。我會在明天早上讀它並嘗試它。會讓你知道它是怎麼回事:) – EpicSyntax