# エンコードとデコード
Swiftでは、データを保存してネットワーク経由で送信する前に、エンコード やシリアライズと呼ばれるプロセスを経て、データを適切な形式に変換する必要があります。
また、ネットワークを介して送信されたデータをプログラムで使用する前に、適切な形式に変換する必要があります。この逆の処理を デコード またはデシリアライズと呼びます。
# Data型
Data型
は、メモリ上のバイト列を管理するため構造体です。Foundationフレームワークが提供しているので、Data型を使うにはFoundationをimportする必要があります。
Data型はさまざまなデータの表現に使用され、ファイルやURLを指定してデータを読み込んだり、メモリのデータをファイルに書き出したりできます。また、画像やJSONを表現する場合などにも使われます。
# JSON
一般的に、アプリがAPIサーバーと通信する場合、データはJSON形式でやりとりすることが多いかと思います。Foundationフレームワークの JSONEncoder
クラスを使用すると、Swiftの値をJSONに変換することができ、JSONDecoder
クラスはJSONをSwiftの値にデコードすることができます。
# JSONEncoder
JSONEncoder
はSwiftの値をJSONに変換します。変換されるSwiftの値は Encodable
プロトコルに準拠する必要があります。
次の例では、JSONEncoder
クラスのインスタンスを生成して、.encode
メソッドを呼び出して変換しています。変換されるUser型は、Encodable
プロトコルに準拠させます。
最後では、実行結果を見るために、エンコードされたバイト列のData型をString型にして表示しています。
import Foundation
// JSONEncoder クラスのインスタンスを生成
let encoder = JSONEncoder()
// Encodableプロトコルに準拠させる
struct User: Encodable {
let id: String
let name: String
}
// Swiftの値をJSON形式にエンコードしてData型として受け取る
let user1 = User(id: "1", name: "Taro")
let encodedData = try encoder.encode(user1)
// JSONの中身を見るためにData型を文字列に変換
let json = String(data: encodedData, encoding: .utf8)!
print(json)
/* 実行結果 */
// {"id":"1","name":"Taro"}
# JSONDecoder
JSONDecoder
はJSONをSwiftの値に変換します。変換される値は Decodable
プロトコルに準拠する必要があります。
.decode
メソッドには、型名とデコードするData型を指定します。
JSONDecoder().decode(型.self, from: デコード対象のData型)
次の例では、エンコードされたバイト列のJSONデータをUser型にデコードしています。User型は、デコードされるために Decodable
に準拠しています。
import Foundation
let encoder = JSONEncoder()
// Decodableに準拠
struct User: Encodable, Decodable {
let id: String
let name: String
}
let user1 = User(id: "1", name: "Taro")
let encodedData = try encoder.encode(user1)
// JSONDecoder クラスのインスタンスを生成
let decoder = JSONDecoder()
// デコードする
let decoded = try decoder.decode(User.self, from: encodedData)
print(decoded)
/* 実行結果 */
// User(id: "1", name: "Taro")
デコードされる対象はData型でないといけないので、JSON形式の文字列を直接指定してもコンパイラはエラーを出力します。
import Foundation
struct User: Encodable, Decodable {
let id: String
let name: String
}
let decoder = JSONDecoder()
// JSON形式の文字列を指定する
let decoded = try decoder.decode(User.self, from: "{\"id\": \"1\", \"name\": \"Taro\"}")
/* 実行結果 */
// error: cannot convert value of type 'String' to expected argument type 'Data'
次のように、文字列をData型に変換させる必要があります。
import Foundation
struct User: Encodable, Decodable {
let id: String
let name: String
}
let decoder = JSONDecoder()
// JSON形式の文字列を指定する
let decoded = try decoder.decode(User.self, from: "{\"id\": \"1\", \"name\": \"Taro\"}".data(using: .utf8)!)
print(decoded)
/* 実行結果 */
// User(id: "1", name: "Taro")