【Swift】JSONデータをエンコードする方法!JSONEncoderクラスの使い方

この記事からわかること

  • SwiftJSONファイル操作するには?
  • エンコードする方法
  • JSONEncoder使い方
  • 構造体をJSONデータ変換する方法

index

[open]

\ アプリをリリースしました /

みんなの誕生日

友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-

posted withアプリーチ

Swiftの構造体をJSONデータに変換する方法をまとめていきたいと思います。

JSONファイルとは?

JSONファイル」とはJavaScriptのオブジェクト形式の記法に準拠した構造で拡張子に「.json」が用いられるテキストデータファイルのことです。様々なプログラミング言語でも扱いが可能ながらもテキストファイルなので軽量なのが大きなメリットです。ちなみにJSONは「JavaScript Object Notation(記法)」の略称です。

JSON形式のデータ

{
  "person": [
    {
        "name": "Ame Tsubaki",
        "age": 18,
        "hobby": ["旅行", "料理", { "web制作": ["HTML", "CSS", "php"] }]
    },
    {
        "name": "Yoshida Takashi",
        "age": 21,
        "hobby": ["読書", "ランニング", "テニス"]
    }
  ]
}

中身は配列と連想配列を組み合わせたような形式になっています。深くネストすることも可能ですが、大枠は連想配列になっているのがJSONファイルの特徴です。

Swiftでも利便性の高いJSONファイルを扱うことが可能です。

SwiftでJSONファイルを扱う

SwiftでJSONファイルを扱う上で注意しなければいけないポイントは以下の通りです。

JSONファイルを扱うポイント

エンコード(encode)とは「符号化」のことで、「一定の規則に準じた形式にデータ変換すること」です。デコード(decode)はその逆で符号化されたデータを元に戻すことをさしています。

今回はエンコードについてまとめていきます。

Swiftの構造体をJSONデータに変換する(エンコード)

Swiftの構造体をJSONデータに変換するためのポイント

Encodableプロトコルに準拠した構造体

Swiftの構造体からJSONデータに変換するためには対象の構造体がEncodableプロトコルに準拠している必要があります。プロトコルはDecodableプロトコルとEncodableプロトコルを兼ねたタイプエイリアス(別名)であるCodableプロトコルを指定しても問題ありません。

struct Person: Encodable {
    var name:String
    var age:Int
    var hobby:String
}

これで構造体の定義が完了したのでJSONに変換したい値を格納しておきます。

let person = Person(name: "Ame", age: 18, hobby: "web制作")

JSONEncoderクラスとは?

エンコードするにはSwiftに標準で定義されている、JSONデータにエンコードするためのJSONEncoderクラスを使用します。エンコードする際にポイントになるのはoutputFormattingプロパティとencodeメソッドです。

struct Person: Encodable {
    var name:String
    var age:Int
    var hobby:String
}

let person = Person(name: "Ame", age: 18, hobby: "web制作")

let encoder = JSONEncoder()

// フォーマットを指定
encoder.outputFormatting = .prettyPrinted

// エンコード
let jsonData = try encoder.encode(person)

// 文字コードUTF8のData型に変換
print(String(data: jsonData , encoding: .utf8)!)

問題がなければ下記のようにJSON形式となって出力されます。

{
  "name" : "Ame",
  "age" : 18,
  "hobby" : "web制作"
}

outputFormattingプロパティ

outputFormattingプロパティエンコードしたJSONデータのインデントやサイズ、順序などを指定できるインスタンスプロパティです。設定できる値は下記のものをから選びます。

未指定

未指定の場合はそのまま出力してくれます。

{"name":"Ame\/Tsubaki","age":18,"hobby":"web制作"}

.prettyPrinted

インデントを自動で付与し、読みやすい形で出力してくれるフォーマット値です。

{
  "name" : "Ame\/Tsubaki",
  "age" : 18,
  "hobby" : "web制作"
}

.sortedKeys

キー値を昇順でソートした状態で出力してくれるフォーマット値です。

{"age":18,"hobby":"web制作","name":"Ame\/Tsubaki"}

.withoutEscapingSlashes

「/(スラッシュ)」が入っている場合にエスケープ文字を付けずに出力するフォーマット値です。

{"name":"Ame/Tsubaki","age":18,"hobby":"web制作"}

encodeメソッド

encodeメソッドはJSONEncoderクラスのジェネリックインスタンスメソッドです。引数に変換したい構造体を渡し、エンコードされたJSONデータが戻り値として帰ってきます。

func encode<T>(_ value: T) throws -> Data where T : Encodable

定義を見るとthrows句があるので異常があった場合に例外が投げられる可能性があります。encodeメソッドの実行にはtry文を使用するのを忘れないように注意してください。

ジェネリックと<T>の意味についてはこちらの記事を参考にしてください。

SwiftでJSONとして扱う型式

エンコードが完了した戻り値はSwiftでJSONデータとして扱う型に適さない可能性があります。Swift内でJSON形式のデータであることを認識させるために明示的に適切な変換をおこなっておきます。

ポイント

SwiftでJSONデータを扱うには文字コード:UTF-8のData型にする

適切なData型に変換する方法は幾つかありますが今回はStringのイニシャライザーを使って変換していきます。

// エンコード
let jsonData = try encoder.encode(person)

// 文字コードUTF8のData型に変換
print(String(data: jsonData , encoding: .utf8)!)

引数には変換したいデータとエンコード値を指定します。エンコード値(String.Encoding)はASCII文字やUTF-8など様々な設定値が用意されています。

イニシャライザーの構文

init?(
  data: Data,
  encoding: String.Encoding
)

ネストされた構造体をJSONデータにエンコードする

構造体の中にさらに構造体が定義されているようなネスト(階層化)されている場合でもエンコードは可能です。

struct School: Encodable {
  var schoolName:String
  var person:[Person]
}

struct Person: Encodable {
    var name:String
    var age:Int
    var hobby:String
}

let school = School(schoolName:"Webエンジニア学習部屋",person:[Person(name: "Ame", age: 18, hobby: "web制作"), Person(name: "Yoshida", age: 21, hobby: "読書")])

let encoder = JSONEncoder()

// フォーマットを指定
encoder.outputFormatting = .prettyPrinted

// エンコード
let jsonData = try encoder.encode(school)

// 文字コードUTF8のData型に変換
print(String(data: jsonData , encoding: .utf8)!)

構造体から変換されたJSONデータ

{
  "person" : [
    {
      "name" : "Ame",
      "age" : 18,
      "hobby" : "web制作"
    },
    {
      "name" : "Yoshida",
      "age" : 21,
      "hobby" : "読書"
    }
  ],
  "schoolName" : "Webエンジニア学習部屋"
}

構造体からJSONデータに変換するプロパティを指定する

定義されている構造体のプロパティの中からJSONデータに変換したくないプロパティがある場合は列挙型(enum)CodingKeysを定義することで変換するプロパティを選択することができます。

例えばhobbyプロパティは変換したくない場合は以下のように定義します。

enum CodingKeysを使った構造体

struct Person: Encodable {
    var name:String
    var age:Int
    var hobby:String
    
    private enum CodingKeys: String, CodingKey {
            case name, age
    }
}

列挙型(enum)を含んだ構造体を変換する

構造体のプロパティに列挙型(enum)を使用している場合は列挙型にもCodableプロトコルへの準拠が必要になります。指定しない場合はType 'Location' does not conform to protocol 'Encodable'のようなエラーになります。

struct Location:  Codable , Identifiable {
    var id = UUID()     // 識別子
    var address:String  // 住所
    var name:String     // 名称
    var memo:String     // メモ
    var spot:Spot       // スポットカテゴリ
}

// 列挙型にもCodableプロトコルへの準拠が必要
enum Spot: String, Codable {
    case house      // 人の家
    case restaurant // 飲食店
    case workplace  // 仕事場
    case shop       // ショップ
    case facility   // 施設
    case leisure    // レジャー
    case nature     // 自然
    case parking    // 駐車場
}

Bool型をJSONに変換時に1や0にする方法

定義したSwiftオブジェクトのプロパティがBool型でもJSONの値をrue/false以外でへ変換させたい場面もあると思います。

詳細はこちらの記事を参考にしてください。

まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。

ご覧いただきありがとうございました。

searchbox

スポンサー

ProFile

ame

趣味:読書,プログラミング学習,サイト制作,ブログ

IT嫌いを克服するためにITパスを取得しようと勉強してからサイト制作が趣味に変わりました笑
今はCMSを使わずこのサイトを完全自作でサイト運営中〜

New Article

index