Alamofire&CodableでAPIからデータを取得する

## はじめに
本稿ではAlamofireとCodableを利用して、APIからデータを取得する処理について説明します。
最近仕事でCodableを使ってみたのですが、意外と使いやすくて初心者の方にもオススメできる機能だったので、備忘録もかねてまとめてみました。

## 環境
macOS 10.13.4
swift 4.1
xcode 9.4.1

## Alamofireの導入

AlamofireはiOSアプリ開発では有名な、汎用的な通信ライブラリです。
インストールはまずPodfileに下の記述をします。

```vim:Podfile

pod 'Alamofire'
```

その後、ターミナル上で以下のコマンドを叩きます。

```
pod install 
```

これでAlamofireのインポートは完了です。

**※注意**
Alamofireをインポートしようとすると、**no such module** というエラーが出るかもしれません。
その場合は、command + b で一度ビルドしてください。エラーが消えます。

## Codableの利用
Codableはswift4から追加された内部機能です。
[Foundation](https://developer.apple.com/documentation/foundation)パッケージ内に定義されているため、Codableを利用する際は必ずFoundationをインポートしましょう。

今回は以下のようなJSONを返すAPIを想定してモデルを作成します。

```json
{
  "id": 0,
  "userName": "dack",
  "imageUrl": "https://hogehoge/image.png"
}
```

さて、まずCodableを利用して、APIから取得したデータを保持するモデルを作成します。
Codableを利用する際は、変数名をJSONのキー名と一致させます。そうすると、以下のようなモデルとなります。

```swift:UserModel.swift
import Foundation

struct UserModel: Codable {
    let id: Int
    let userName: String
    let imageUrl: String
}
```

これでモデルは完成です。

## JSONのデコード
モデルが完成したので、実際にAlamofireで取得したJSONをデコードしてモデルに格納します。
AlamofireでJSONを取得し、デコードする処理は以下のようになります。

```swift:APIViewController.swift
import Alamofire

func request() {
  // APIリクエスト
  Alamofire.request("https://hogehoge/get"
                    method: .get,
                    parameters: nil,
                    encoding: JSONEncoding.default,
                    headers: nil)
    .response { response in
        guard let data = response.data else { return }
        let userModel: UserModel = JSONDecoder().decode(UserModel.self, from: data)
        print(userModel)
        // printの出力結果
        // (id: 0, userName: dack, imageUrl: https://hogehoge/image.png)
    })
}
```

返却されるJSONと対応していれば、Codableで作成したモデルにデコード結果がそのまま反映されます。
後は使いたいようにモデルに格納された値を良しなに使用しましょう。

## ネストしたJSONのデコード
上記のような単純なJSONなら分かりやすいですが、実際の現場だとJSONがネストすることはザラです。
ですが、Codableを利用すれば簡単にネストしたJSONもデコードしてモデルに格納できます。
例として以下のようなJSONをデコードします。

```json
{
  "id": 0,
  "name": "dack",
  "information": {
    "age": 25,
    "sex": "male",
    "job": "engineer" 
    },
  "follows": ["john", "nancy", "zushi"]
}
```

このJSONをデコードするモデルは以下のようになります。

```swift:UserModel.swift
import Foundation

struct UserModel: Codable {
    let id: Int
    let name: String
    let information: InformationModel
    let follows: [String]
}

struct InformationModel: Codable {
    let age: Int
    let sex: String
    let job: String
}
```

JSONのオブジェクト = SwiftのStruct(構造体)と考えると分かりやすいですね。
AlamofireでJSONを取得して、デコードした結果をモデルに格納する方法は変わらず簡単にできます。

```swift:APIViewController.swift

func request() {
  // APIリクエスト
  Alamofire.request("https://hogehoge/get2"
                    method: .get,
                    parameters: nil,
                    encoding: JSONEncoding.default,
                    headers: nil)
    .response { response in
        guard let data = response.data else { return }
        let userModel: UserModel = JSONDecoder().decode(UserModel.self, from: data)
        print(userModel)
        // printの出力結果
        // (id: 0, userName: dack, information: (age: 25, sex: male, job: engineer), follows: (john, nancy, zushi))
    })
}
```

以上で、AlamofireとCodableを利用したAPIからデータの取得ができるようになりました。
モデルをCodableで作成して、Alamofireで取得したJSONをデコードするだけなので、見た目以上に簡単に実現できます。
ただし、JSONのキー名とモデルの変数名が異なるとデコードできずにモデルにデータを格納することができないため、注意が必要です。

## 最後に
いかがでしたでしょうか？
JSONのシリアライズには[ObjectMapper](https://github.com/Hearst-DD/ObjectMapper)や[SwiftyJson](https://github.com/SwiftyJSON/SwiftyJSON)等の有名なライブラリがありますが、Codableは内部機能でモデルも構造体で定義できるためとっつきやすいかと思います。是非使ってみて下さい。