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

Swift で JSON の読み書き 1


このように 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 の読み書き 2


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"
}

Swift で JSON の読み書き 3

Encodable ではなく Codable をコンフォームしている場合は、Decodable をコンフォームする為に、CodingKeys に含まれていないプロパティに初期値を設定する必要があります。


以上、Swift で JSON の読み書きをする方法についてご説明しました。

© 2024 iOS 開発入門