Cloud Translation APIのJSONをSwift4のCodableで楽だった

# Codableに早く手を出せばよかった。

Googleの翻訳API「Cloud Translation API」を使ってみようと手を出すも、返ってきたJSON形式データの配列、オブジェクトにつまづく。

Swift4に加わったCodableを使ったところ、思った以上にあっさり解決した。

## POSTデータ

```swift
var jsonObject = Dictionary<String,Any>()
jsonObject["q"] = "Hello"
jsonObject["source"] = "en"
jsonObject["target"] = "ja"
jsonObject["format"] = "text"
```

## レスポンス用構造体

```swift
struct GcpTranslationJson:Codable {
    let data: Data
    struct Data:Codable {
        let translations: [Translations]
    }
    struct Translations:Codable {
        let translatedText: String
    }
}
```

## POSTしてレスポンス処理まで

### 全体

```swift
func post(url urlString: String, postParameter: [String:Any]) {
    var request = URLRequest(url: URL(string: urlString)!)
    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    do {
        request.httpBody = try JSONSerialization.data(withJSONObject: postParameter, options: .prettyPrinted)
    } catch {
        print(error.localizedDescription)
    }

    let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
        if let data = data, let response = response {
            do {
                print("JSONSerialization")
                let json = try JSONDecoder().decode(GcpTranslationJson.self, from: data)
                print(json.data.translations[0].translatedText)
            } catch {
                print("Error")
            }
        }
    })
    task.resume()
}
```

`Codable`で楽になったJSON形式データから値の引き出し。

```swift
let json = try JSONDecoder().decode(GcpTranslationJson.self, from: data)
print(json.data.translations[0].translatedText)
```

`output`を見ると翻訳された文が出力されてた。

```
こんにちは
```

## まとめ

* Codableは楽。
* クラウドサービスの利用者側セキュリティは適切に（API制限や管理等）
* お財布に優しかったクラウドサービス

コードのコピペはある段階で限界がくる。社蓄ちゃんに怒られないようにコピペコードへの理解を深めよう（今回はJSON構造解説とCodable解説を読んで解決できた）。

* 結局、Codableを使わない方法はわかってない。
* URLSession周りも怪しい。

## 参考

* [[Swift 4] SwiftyJSONを使わずにシンプルにJSONをデータ構造化する ｜ Developers.IO](https://dev.classmethod.jp/smartphone/json-decoding-without-swiftyjson/)
* [Ultimate Guide to JSON Parsing with Swift 4 - Ben Scheirman](http://benscheirman.com/2017/06/ultimate-guide-to-json-parsing-with-swift-4/)
* [ルートが配列のJSONをCoadableでカスタムモデルにマッピングする - Qiita](https://qiita.com/matsuda/items/ee6d02570f716da765e9)

* [非エンジニアに贈る「具体例でさらっと学ぶJSON」 ｜ Developers.IO](https://dev.classmethod.jp/etc/concrete-example-of-json/)
* [【輪講】JSONの書き方 | TRIDENT Mobile &amp; Network Lab. Blog](http://www.trident-game.com/blog/2015/10/14/%E3%80%90%E8%BC%AA%E8%AC%9B%E3%80%91json%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9/)

# 以下、試行錯誤の残滓（一部）

## GET時のレスポンス

* URL

```
https://translation.googleapis.com/language/translate/v2?source=en&target=ja&q=hello&key={API Key}
```

* Response

```
{
  "data": {
    "translations": [
      {
        "translatedText": "こんにちは"
      }
    ]
  }
}
```

## XCodeのブレイクポイントで変数`json`を「!」マークで中を見ると

```
▿ 1 element
  ▿ 0 : 2 elements
    - key : "data"
    ▿ value : 1 element
      ▿ 0 : 2 elements
        - key : translations
        ▿ value : 1 element
          ▿ 0 : 1 element
            ▿ 0 : 2 elements
              - key : translatedText
              - value : こんにちは
```

## 失敗コード

2行目の部分で停止。

```swift
let jsonData = json["data"] as! [String:Any]
let jsonTranslations = jsonData["translations"] as! NSDictionary
let jsonTranslation = jsonTranslations.first as! [String:Any]
let jsonTranslatedText = jsonTranslation["translatedText"] as! String
```

他に２０個弱試して消してた、と思う。