web-dev-qa-db-ja.com

Swift 4コード可能配列

オブジェクトのJSON配列を返すAPIルートがあります。例えば:

[
    {"firstname": "Tom", "lastname": "Smith", "age": 31},
    {"firstname": "Bob", "lastname": "Smith", "age": 28}
]

Swiftの新しいコード化可能な機能を使用して、クラス内の2つのオブジェクトに変換する方法を想像しようとしています。その応答とそれは私に二人のオブジェクトを提供しています。

また、リクエストを処理するためにAlamofireを使用しています。

これどうやってするの?これまでのところ、コーディング可能なものに関連して私が見たすべてのものは、1つのオブジェクトのみを許可します。また、AlamofireやWebフレームワークとの統合も見ていません。

15
Charlie Fish

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は例外をスローします)

17
nathan

コード化可能なオブジェクトへのデータ応答をシリアル化できました。

あなたはすべてjsonオブジェクト_[String: String]_の変換に慣れているかもしれません。そのjsonオブジェクトは、json.data(using: .utf8)!を使用してDataに変換する必要があります。

Alamofireを使用すると、そのデータ(または、少なくとも_.utf8_の事柄と既に互換性のあるこの種類のデータが機能する)を簡単に取得できます。

_func responseData(queue: DispatchQueue?, completionHandler: @escaping (DataResponse<Data>) -> Void) -> Self
_

次に、そのデータをDecodercompletionHandlerの入力として使用します

_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)
        }
    }
_
0
abbawssdsad