SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Swift 4で最初に知っておきたい3つのポイント

Swift 4の新機能――拡張されたDictionary、JSON解析に役立つCodableプロトコル

Swift 4で最初に知っておきたい3つのポイント 第2回

JSONの解析

 ゲームアプリやメッセージアプリなど、外部のサーバーとAPIでやり取りをするアプリは日々増えつつあります。APIを介したデータのやり取りで最も多く使われるフォーマットはJSONです。Swift 4ではJSONを解釈する際に、JSON内の各値を自動で構造体にマッピングできるCodableプロトコルが実装されました。

Codableプロトコルを実装した構造体を定義する【Swift 4】

 JSONデータの例として、本記事ではランダムにユーザー情報を生成するRANDOM USER GENERATOR APIからの戻り値を利用します。RANDOM USER GENERATOR APIにブラウザからアクセスすると、下図の構造をしたJSONが確認できます。

RANDOM USER GENERATOR APIのJSONの構造
RANDOM USER GENERATOR APIのJSONの構造

 resultsのキーの下層にユーザー情報が格納されています。

 この構造のJSONを解析するために、JSONの構造に対応した2つの構造体を定義します。

  • (1)ユーザー情報を配列で格納しているresultsに対する構造体
  • (2)ユーザー情報を格納する構造体

 (1)をResultListModel、(2)をPersonの名前で次の通り定義します。

リスト7 JsonViewController.swift
// resultsを格納する構造体
struct ResultListModel:Codable{    // ------(1)
    let results : [Person]
}

// ユーザー情報を格納する構造体
struct Person: Codable  {    // ------(2)
    let gender: String
    
    let name: Name    // ------(3)
    struct Name: Codable  {
        let title: String
        let first: String
        let last: String
    }
    
    let location: Location
    struct Location: Codable  {
        let street: String
        let city: String
        let state: String
        let postcode: Int
    }
    
    let email: String
# 略
}

 ResultListModel構造体に関しては、JSON構造のresultsに対してユーザー情報を配列で持つ定義のみです(1)。Codableプロトコルを忘れないように実装しておきます。

 Person構造体は、対応するJSONの構造の通りにプロパティを定義します(2)。StringやIntの場合は、通常のプロパティと同様に定義します。JSONの構造に階層がある場合は、その階層も構造体としてPerson構造体の中に定義します(3)。解析するJSONの構造とPerson構造体の関係は下図の通りです。

解析するJSONの構造とPerson構造体の関係
解析するJSONの構造とPerson構造体の関係

 このように、Codableプロトコルを実装した構造体を定義しておきます。

JSONを解析する【Swift 4】

 作成した2つの構造体を使って実際にJSONを解析します。APIへのアクセスに関してはSwift 3以前と同じく、URL→URLRequest→URLSession→URLSessionDataTaskの各クラスを利用して行います。

リスト8 JsonViewController.swift(APIへのアクセス)
//  RANDOM USER GENERATORのAPIにアクセスし、APIの結果をJSONで取得
let str : String = "https://randomuser.me/api"
let url : URL = URL(string: str)!

// URLRequestを生成してJSONのデータを取得
let request: URLRequest = URLRequest(url:url)
let session = URLSession.shared
let task : URLSessionDataTask = session.dataTask(with: request, completionHandler: {(data, response, error) in
    
    // APIからの戻り値がなければ処理を終了
    guard let responseData = data else{ return }    // ------(1)
    
# 略
})
task.resume()

 処理の進め方はリスト8のように、従来通りに行います。guard文による、APIからの戻り値がない場合の処理もSwift 3と同様です(1)。

 guard文以降で、Swift 4から追加されたJSONDecoderクラスのdecodeメソッドを利用します。利用時の書式は次の通りです。

書式4 JSONDecoderクラスによるJSONの解析
let decoder = JSONDecoder()
let 構造体オブジェクト = try decoder.decode(構造体の名前, from: Dataオブジェクト)

 書式の処理の内容は次の通りです。

  1. JSONDecoderクラスのインスタンスを生成
  2. Codableプロトコルを実装した構造体とDataオブジェクトを引数にdecodeメソッドを実行

 この2行だけで、作成した構造体の通りにJSONのデータがマッピングされます。DataオブジェクトはAPIからの戻り値で、URLSessionDataTaskクラスから渡される値をそのまま利用できます。サンプルでの実際の利用例は次の通りです。

リスト9 JsonViewController.swift(JSONの解析)
do {    // ------(1)
    // JSONDecoderクラスのインスタンスを生成
    let decoder = JSONDecoder()    // ------(2)
    // JSONを解析して作成した構造体の通りにマッピング
    let resultList = try decoder.decode(ResultListModel.self, from: responseData)    // ------(3)
    print(resultList)
    
    // JSONを解析した後、Person構造体にマッピングされたデータを取り出す
    for person in resultList.results {      //   出力の例     // ------(4)
        print(person.gender)                   //   female
        print(person.name.title)              //    madame
        print(person.location.state)        //     ticino
        print(person.email)                     //    leana.aubert@example.com
    }
} catch {
    print("JSONの解析でエラーが起きました")
}

 JSONDecoderクラスのdecodeメソッドは、throwsでエラーを投げる仕様になっているので、do-catch文の中に記述します。その中で、JSONDecoderクラスのインスタンスを生成(2)、decodeメソッドを実行します(3)。decodeメソッドに渡す変数は、解析するJSONの構造に対応したResultListModel構造体とAPIからの戻り値のresponseDataです。ResultListModel構造体には後ろにselfをつけて構造体自身をインスタンスとします。これでJSONのデータがオブジェクトにマッピングされます。

 前項で定義したResultListModel構造体と、Person構造体のプロパティで解析したJSONのデータを取り出せます(4)。また、ResultListModel構造体のresultsプロパティでユーザー情報を格納したPersonの配列を参照できます。for文で回してPerson構造体の各プロパティで対応するJSONの値を参照することも可能です。

 RANDOM USER GENERATOR APIの仕様上、呼び出すたびにランダムにユーザー情報が変わるので、サンプルを実行するたびに出力結果も変わります。

 Swift 3以前では、APIから取得した戻り値をオブジェクトに変換したり、map関数やflatMap関数を何度も利用してJSON内の目的の値を取り出したりしていました。Swift 4では、これらの作業が必要なくなるだけでなく、JSONのフォーマットを構造体として定義できるため、JSONの書式が変わった際の対応なども容易にできます。

まとめ

 今回はSwift 4で追加された、よく利用される便利な機能について説明しました。Swiftのバージョンアップに伴う新しい仕様は、いかに従来の処理を短縮化できるかに重点が置かれていると思われます。iOSやSwiftのバージョンアップが行われる際には、Apple Developerのドキュメントを確認して新しい機能を使ってみてください。

 次回は動的な画面を作成するためによく利用される処理について説明します。

参考資料

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Swift 4で最初に知っておきたい3つのポイント連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 片渕 彼富(カタフチ カノトミ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/10532 2017/12/08 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー