Categories
SugiBlog ホームページ制作・システム開発

WEBから取得したJSONデータを解析しRealmに取り込む

何やらタイトルが長くなってしまいましたが、複合的な内容なのでこうなりました。
今回やりたかったことはタイトルの通りですが、分解すると…
1)WEBからデータをダウンロード
2)バックグラウンドで処理を実行
3)JSONデータを解析
4)解析したデータをRealmに挿入
以上の4つです。

エラーが出なくなるまでかなり苦労したのですが、一番の原因は日本語の扱いに関する部分ですので、
日本語を含まないデータの解析だけならすんなり可能ではないかと思います。

1)WEBからデータをダウンロード

WEBからデータをダウンロードするにはURLSessionを使います。

ダウンロードするURLを指定

let url: String = "http://www.exam.jp/json.php"

セッションを作成します。

let session = URLSession(configuration: URLSessionConfiguration.default)

タスクを登録します。

let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: {
    (data, response, error) in

    if let urlContent = data {
        // ここに処理を記述
    }

})

作成したタスクを実行します。

task.resume()

2)バックグラウンドで処理を実行

バックグラウンドで処理を実行するには、GCD(Grand Central Dispatch)を使用します。

DispatchQueue.global().async {
    // バックグラウンドスレッドでの処理を記述
}

asyncだと非同期処理、syncだと同期処理になります。

3)JSONデータを解析

取得したJSONデータをJSONSerializationクラスを使って解析します。

let jsonObj = try! JSONSerialization.jsonObject(with: urlContent, options: [])

JSONデータが配列の場合は以下のようになります。

let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray

4)解析したデータをRealmに挿入

解析したJSONデータをRealmデータベースに挿入します。
ここで注意点ですが、JSONの構造とRealmモデルの構造が同じである必要があります。

まずはRealmモデルを定義します。

class realmModel: Object {
    dynamic var id = 0
    dynamic var name = ""

    // プライマリキーの定義
    override class func primaryKey() -> String? {
        return "id"
    }
}

取得するJSONデータ

{ "id": 1, "name": "alpha" }
let realm = try! Realm()

do {

    try realm.write {
        let jsonObj = try! JSONSerialization.jsonObject(with: urlContent, options: [])
        let myData = realmModel(value: jsonObj)
    }

} catch {

}

JSONデータが配列の場合

取得するJSONデータ

[{ "id": 1, "name": "alpha" },{ "id": 2, "name": "beta" }]
try realm.write {

    let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray

    for item in list {
        let myData = realmModel(value: item)
        print(myData) //デバッグ用に出力
        realm.add(myData, update: true)
    }

}

まとめると以下のようになります。

let url: String = "http://www.exam.jp/json.php"

let session = URLSession(configuration: URLSessionConfiguration.default)

let task = session.dataTask(with: URLRequest(url: Foundation.URL(string: url)!), completionHandler: {
    (data, response, error) in
    
    if let urlContent = data {

        // バックグラウンドで処理を実行する。
        DispatchQueue.global().async {
            let realm = try! Realm()
            do {
                
                try realm.write {

                    let list = try! JSONSerialization.jsonObject(with: urlContent, options: []) as! NSArray
                    
                    for item in list {
                        let myData = realmModel(value: item)
                        print(myData) //デバッグ用に出力
                        realm.add(myData, update: true)
                    }

                }

            } catch {
                
            }
            
        }

    }
    
})
task.resume()

Xcode: 8.3.2
Swift: 3.1
OS: Sierra 10.12

72 views

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*