Swift で JSON の読み書き
ここでは Swift で JSON の読み書きをする方法についてご説明します。
JSON 文字列を Swift のオブジェクトへ変換する
今回は JSONDecoder を使って、JSON の文字列から Swift の struct のオブジェクトに変換する方法をご紹介します。
次のような JSON 文字列を変換します。
{
"name": "Haruka",
"age": 20,
"email": "haruka@mail.com"
}
JSON の情報を保持するための struct を定義します。
JSONDecoder を使ってデコードするためには Decodable の protocol を conform していなければなりません。
Codable は Decodable と Encodable のタイプエリアスなので、Codable を conform しても大丈夫です。
次のような Person struct を定義しておきます。プロパティー名が JSON と合っていないとエラーになります。
struct Person: Decodable {
var name: String
var age: Int
var email: String
}
先ほどの JSON 文字列を JSONDecoder を使って、Person struct に変換するには次のようにできます。
import Foundation
struct Person: Decodable {
var name: String
var age: Int
var email: String
}
let jsonData = """
{
"name": "Haruka",
"age": 20,
"email": "haruka@mail.com"
}
""".data(using: .utf8)!
let person = try JSONDecoder().decode(Person.self, from: jsonData)
print(person.name)
print(person.age)
print(person.email)
実行結果は次のようになり、person オブジェクトに変換できているのがわかります。
Haruka
20
haruka@mail.com
JSON 文字列を追加のプロパティがある Swift のオブジェクトへ変換する
先ほどは、JSON と全く同じプロパティを持つ struct を定義して変換しましたが、struct に追加で他のプロパティを定義したいこともあると思います。
上記のコードに struct に JSON にないプロパティを追加すると decode しようとした時にエラーになってしまいます。
例えば、上の Person struct に nickname というプロパティーを追加して実行すると以下のようなエラーになります。
▿ DecodingError
▿ keyNotFound : 2 elements
- .0 : CodingKeys(stringValue: "nickname", intValue: nil)
▿ .1 : Context
- codingPath : 0 elements
- debugDescription : "No value associated with key CodingKeys(stringValue: \"nickname\", intValue: nil) (\"nickname\")."
- underlyingError : nil
このように JSON 文字列に含まれていないプロパティを持たせたい時には、その追加のプロパティに初期値を設定し、CodingKeys に JSON に含まれているデコードされるプロパティを定義することによって、エラーを出さずに decode することが可能です。
import Foundation
struct Person: Decodable {
var name: String
var age: Int
var email: String
var nickname: String = ""
private enum CodingKeys: String, CodingKey {
case name, age, email
}
}
let jsonData = """
{
"name": "Haruka",
"age": 20,
"email": "haruka@mail.com"
}
""".data(using: .utf8)!
let person = try JSONDecoder().decode(Person.self, from: jsonData)
print(person.name)
print(person.age)
print(person.email)
実行結果は次の通りで、エラーにならずに decode されています。
Haruka
20
haruka@mail.com
Swift のオブジェクトから JSON 文字列へ変換する
次は反対で、Swift のオブジェクトから JSON 文字列への変換してみましょう。
今回は JSONEncoder を使って、Swift の struct から JSON 文字列を生成します。
JSONEncoder を使ってデコードするためには Encodable の protocol を conform していなければなりません。
Codable は Decodable と Encodable のタイプエリアスなので、Codable を conform しても大丈夫です。
Person struct のオブジェクトから JSON 文字列を生成するには次のようにできます。
import Foundation
struct Person: Encodable {
var name: String
var age: Int
var email: String
var nickname: String
}
let person = Person(name: "Ryota", age: 16, email: "ryota@gmail.com", nickname: "Ryo")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try encoder.encode(person)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
実行結果は次のようになり、person からJSON 文字列に変換できていますね。
{
"age" : 16,
"email" : "ryota@gmail.com",
"nickname" : "Ryo",
"name" : "Ryota"
}
Swift のオブジェクトから特定のプロパティのみ JSON 文字列へ変換する
Swift のオブジェクトから特定のプロパティのみ JSON 文字列へ変換したい時には、CodingKeys を定義して JSON 含めたいプロパティを指定します。
例えば、先ほどの Person struct のプロパティのうち、name と email のみを JSON 文字列に変換したいのであれば、次のようにできます。
import Foundation
struct Person: Encodable {
var name: String
var age: Int
var email: String
var nickname: String
private enum CodingKeys: String, CodingKey {
case name, email
}
}
let person = Person(name: "Ryota", age: 16, email: "ryota@gmail.com", nickname: "Ryo")
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let jsonData = try encoder.encode(person)
let jsonString = String(data: jsonData, encoding: .utf8)!
print(jsonString)
実行結果は次のようになり、"name" と "email" のみが JSON 文字列に含まれています。
{
"name" : "Ryota",
"email" : "ryota@gmail.com"
}
Encodable ではなく Codable をコンフォームしている場合は、Decodable をコンフォームする為に、CodingKeys に含まれていないプロパティに初期値を設定する必要があります。
以上、Swift で JSON の読み書きをする方法についてご説明しました。