オブジェクトのJSON配列を返すAPIルートがあります。例えば:
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
Swiftの新しいコード化可能な機能を使用して、クラス内の2つのオブジェクトに変換する方法を想像しようとしています。その応答とそれは私に二人のオブジェクトを提供しています。
また、リクエストを処理するためにAlamofireを使用しています。
これどうやってするの?これまでのところ、コーディング可能なものに関連して私が見たすべてのものは、1つのオブジェクトのみを許可します。また、AlamofireやWebフレームワークとの統合も見ていません。
Alamofire 5に関する更新:responseJSONDecodable
。
struct Person: Codable {
let firstName, lastName: String
let age: Int
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
}
Alamofire.request(request).responseJSONDecodable { (response: DataResponse<Person>) in
print(response)
}
Alamofire 4は、現時点ではCodableサポートを追加しません( #2177 を参照)。代わりにこの拡張機能を使用できます: https://github.com/Otbivnoe/CodableAlamofire 。
let jsonData = """
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
""".data(using: .utf8)!
struct Person: Codable {
let firstName, lastName: String
let age: Int
enum CodingKeys : String, CodingKey {
case firstName = "firstname"
case lastName = "lastname"
case age
}
}
let decoded = try! JSONDecoder().decode([Person].self, from: jsonData)
サンプル: http://Swift.sandbox.bluemix.net/#/repl/59a4b4fad12904461159082
CodableAlamofireの使用:
let decoder = JSONDecoder()
Alamofire.request(url).responseDecodableObject(keyPath: nil, decoder: decoder) { (response: DataResponse<[Person]>) in
let persons = response.result.value
print(persons)
}
keypath
は、結果がJSON構造に含まれるパスに対応します。例えば:
{
"result": {
"persons": [
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
}
}
keypath
=> results.persons
[
{"firstname": "Tom", "lastname": "Smith", "age": 31},
{"firstname": "Bob", "lastname": "Smith", "age": 28}
]
keypath
=> nil
(空のkeypath
は例外をスローします)
コード化可能なオブジェクトへのデータ応答をシリアル化できました。
あなたはすべてjsonオブジェクト_[String: String]
_の変換に慣れているかもしれません。そのjsonオブジェクトは、json.data(using: .utf8)!
を使用してData
に変換する必要があります。
Alamofireを使用すると、そのデータ(または、少なくとも_.utf8
_の事柄と既に互換性のあるこの種類のデータが機能する)を簡単に取得できます。
_func responseData(queue: DispatchQueue?, completionHandler: @escaping (DataResponse<Data>) -> Void) -> Self
_
次に、そのデータをDecoder
のcompletionHandler
の入力として使用します
_let objek = try JSONDecoder().decode(T.self, from: data)
_
また、ドキュメントから少し調整して、これを一般的なシリアル化関数にすることもできます
この変更に
_func responseCodable<T: Codable>(
queue: DispatchQueue? = nil,
completionHandler: @escaping (DataResponse<T>) -> Void)
-> Self
{
let responseSerializer = DataResponseSerializer<T> { request, response, data, error in
guard error == nil else { return .failure(BackendError.network(error: error!)) }
guard let data = data else {
return .failure(BackendError.objectSerialization(reason: "data is not valid"))
}
do{
let objek = try JSONDecoder().decode(T.self, from: data!)
return .success(objek)
} catch let e {
return .failure(BackendError.codableSerialization(error: e))
}
}
return response(queue: queue, responseSerializer: responseSerializer, completionHandler: completionHandler)
}
_
サンプル構造
_struct Fids: Codable {
var Status: Status?
var Airport: Airport?
var Record: [FidsRecord]
}
_
この方法で関数を使用する
_ Alamofire.request("http://whatever.com/zzz").responseCodable { (response: DataResponse<Fids>) in
switch response.result{
case .success(let value):
print(value.Airport)
// MARK: do whatever you want
case .failure(let error):
print(error)
self.showToast(message: error.localizedDescription)
}
}
_