SwiftでのJSONのパースは構造体？辞書？

今回はJSONをパースする際、どっちの方がいいのかが気になったので検証してみました。
検証が甘いかもしれませんが多めにみてください

# どっちが楽か
これは検証するまでもなく圧倒的に辞書の勝利です

JSONの情報量が少なければ構造体も苦ではありませんが返ってくるKeyの数が300件+ネストも深いともなってくると苦行です

# 速度
実はこれがメインです
構造体の方が早いのは予想がつくのですがどのくらい差があるのかが気になったので検証してみました。

**計測の方法**
こちらの記事の計測方法を使いました

https://qiita.com/osamu1203/items/9160f5f4951ebe205ea3

**取得するJSON**
TwitterAPIのJSONを使用します
```
https://api.twitter.com/1.1/users/show.json
```

**HTTP通信**
```Swift
    // 構造体でパース
    public func user_info(screen_name: String) async throws -> UserInfo {
        let guest_token = try await generate_guest_token().guest_token
        let url = URL(string: "https://api.twitter.com/1.1/users/show.json?screen_name=\(screen_name)")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.addValue("Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", forHTTPHeaderField: "authorization")
        request.addValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", forHTTPHeaderField: "User-Agent")
        request.addValue(guest_token, forHTTPHeaderField: "x-guest-token")
        let (data, _) = try await URLSession.shared.data(for: request)
        let user_info = try JSONDecoder().decode(UserInfo.self, from: data)
        return user_info
    }

    // 辞書でパース
    public func user_info(screen_name: String) async throws -> [String: Any] {
        let guest_token = try await generate_guest_token().guest_token
        let url = URL(string: "https://api.twitter.com/1.1/users/show.json?screen_name=\(screen_name)")!
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.addValue("Bearer AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA", forHTTPHeaderField: "authorization")
        request.addValue("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", forHTTPHeaderField: "User-Agent")
        request.addValue(guest_token, forHTTPHeaderField: "x-guest-token")
        let (data, _) = try await URLSession.shared.data(for: request)
        let user_info = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
        return user_info ?? [:]
    }
```

こんな感じです
HTTP通信の処理に違いはありません



こちらが作成した構造体です
長いので画像だけ載せます
![スクリーンショット 2022-04-22 13.39.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7d9fa9d0-b51c-538d-e49a-d5c1b4e99a9e.png)

### いざ検証！！
構造体と辞書ともに30回の処理速度を計測して平均を比較してみたいと思います。

|回数|構造体|辞書|
|-|-|-|
|1|0.421766996383667|0.48710501194000244|
|2|0.4457869529724121|0.4717440605163574|
|3|0.44557106494903564|0.4696040153503418|
|4|0.42271196842193604|0.49256694316864014|
|5|0.44592905044555664|0.47148895263671875|
|6|0.4459249973297119|0.4711570739746094|
|7|0.424003005027771|0.49338698387145996|
|8|0.42439305782318115|0.4934580326080322|
|9|0.4237560033798218|0.47139596939086914|
|10|0.42368102073669434|0.4724550247192383|
|11|0.42344892024993896|0.4737999439239502|
|12|0.42438793182373047|0.4938730001449585|
|13|0.42647695541381836|0.47372591495513916|
|14|0.4473719596862793|0.47147297859191895|
|15|0.42362499237060547|0.4707820415496826|
|16|0.44748401641845703|0.4732930660247803|
|17|0.4240630865097046|0.471979022026062|
|18|0.4490799903869629|0.4713670015335083|
|19|0.42538297176361084|0.49446797370910645|
|20|0.4752979278564453|0.49462997913360596|
|21|0.431210994720459|0.502689003944397|
|22|0.43148505687713623|0.4725559949874878|
|23|0.4548109769821167|0.4729820489883423|
|24|0.4322160482406616|0.4967290163040161|
|25|0.4342590570449829|0.4732940196990967|
|26|0.4346250295639038|0.4735100269317627|
|27|0.43521392345428467|0.47393298149108887|
|28|0.43390095233917236|0.4742039442062378|
|29|0.4347410202026367|0.49745798110961914|
|30|0.44629597663879395|0.47441208362579346|
|平均|0.4352967302|0.479850669702|

### 結果
構造体は辞書より0.04455393950200004秒速い

# 結論
**楽さを求める人**
圧倒的に辞書がおすすめです！！

**速度を求める人**
1回だけ取得する人 -> 辞書がおすすめです
複数回の取得する人　-> 構造体がおすすめです


1回の取得だけなら人間には分からないレベルの差です
しかし、複数回取得する場合、数秒の差が生まれます

ユーザーにとってローディングの1秒はかなり大きいです
構造体を作成するのは苦行ですがユーザーの1秒の為に頑張りましょう！！

# 追記(2022/9/10)
Codableに準拠した構造体を自動で生成してくれるサイト見つけました。
JSONをペーストするだけで自動生成してくれます。

https://app.quicktype.io/