iOS・AndroidSwift

【Swift】Codableを用いてJSONデータを読み込む

iOS・Android
この記事は約6分で読めます。

Codableとは

API通信等で取得したJSONやプロパティリストを任意のデータ型に変換するタイプエイリアス。

EncodableとDecodableとの関係性

Encodable + Decodable = Codable

typealias Codable = Decodable & Encodable

既存の型の多くはCodableに準拠しています。

日頃あまり意識していませんが、一定の規則に基づいた型同士の変換が行えるのは、Codableのおかげです。

Decodable | Apple Developer Documentation
A type that can decode itself from an external representation.
Encodable | Apple Developer Documentation
A type that can encode itself to an external representation.

サンプルデータ

下記のJSONをstructとして読み込みます。

JSONファイルをプロジェクト直下のディレクトリに配置します。

{
"name": "xx大会",
    "outa": [
        {
            "title": "犬のおまわりさん",
            "sections": [
                {
                    "sec": 0,
                    "labelname": "前奏"
                },
                {
                    "sec": 17,
                    "labelname": "1番"
                },
                {
                    "sec": 30,
                    "labelname": "2番"
                }
            ],
            "point": "歌唱のポイント歌唱のポイント歌唱のポイント歌唱のポイント",
            "siryouId": "000000001"
        },
],
    "siryou": [
        {
            "id": "000000001",
            "title": "犬のおまわりさん",
            "images": [
                "01", "02", "03", "04", "05"
            ],
            "musicGenre": "童謡",
            "point": "ポイントポイントポイント"
        },
]
}

まずは Codable を適用した struct を作成します。

struct TournamentModel: Codable {
    /// 大会名
    var name: String
    /// おうたのリスト
    var outa: [OutaModel]
    /// 資料のリスト
    var siryou: [SiryouModel]
}

struct OutaModel: Identifiable, Codable {
    
    let id = UUID()
    /// 曲のタイトル
    let title: String
    
    /// 前奏 1番などのラベル
    let sections: [SectionModel]
    
    /// 指導のポイント
    let point: String
    
    let siryouId: String?
    
    enum CodingKeys: String, CodingKey {
        case title
        case sections
        case point
        case siryouId
    }
}

struct SiryouModel: Identifiable, Codable {
    
    let id: String
    let title: String
    let images: [String]
    let musicGenre: String
    let point: String

    enum CodingKeys: String, CodingKey {
        case id
        case title
        case images
        case musicGenre
        case point
    }
}

TournamentModel変数を作成します。

JSONファイルの読み込みとデコードを行う変数loadContentを作成します。

    func loadContent() {
        guard let url = Bundle.main.url(forResource: "setting", withExtension: "json") else {
            fatalError("ファイルが見つからない")
        }

        guard let data = try? Data(contentsOf: url) else {
            fatalError("ファイル読み込みエラー")
        }

        let decoder = JSONDecoder()
        do {
            tournamentModel = try decoder.decode(TournamentModel.self, from: data)
        } catch {
            print(error)
            fatalError("JSON読み込みエラー")
        }
    }

tournamentModel = try decoder.decode(TournamentModel.self, from: data)でJSONに変換します。

あとは適当なタイミングでの loadContent()を実行し、適当なプロパティに代入すれば、JSONデータをSwiftのオブジェクトとして扱うことができるようになります。

参考

Encoding and Decoding Custom Types | Apple Developer Documentation
Make your data types encodable and decodable for compatibility with external representations such as JSON.