post Image
ルートが配列のJSONをCoadableでカスタムモデルにマッピングする

Swift4で新しく追加されたCodableを利用して、ルートが配列のJSONをそのままCodableを適用したモデルの配列にマッピングするのではなく、該当する配列をプロパティとして持つCodableを適用したコンテナ的なモデルにマッピングする方法が見つからず、色々調べた結果、対応方法がわかったので記しておく。

ルートが配列のJSON

例えばGithub APIのGet all usersのレスポンスは

[
  {
    "login": "mojombo",
    "id": 1,
    "url": "https://api.github.com/users/mojombo",
    ...
    "site_admin": false
  },
  {
    "login": "defunkt",
    "id": 2,
    "url": "https://api.github.com/users/defunkt",
    ...
    "site_admin": true
  },
  ...
]

とJSONのルートが配列になっている。

モデル

上記のJSONをアプリで利用するために、Codableを適用したUserモデルを以下のように作成する。

struct User: Codable {
    let id: Int
    let login: String
    let url: String
}

デコード

単純にこのモデルオブジェクトの配列にデコードするのであれば、

let users: [User] = try JSONDecoder().decode([User].self, from: data)

で可能。

コンテナモデル

上記のように配列にデコードしたモデルをアプリ内で受け渡しながら使いまわすよりも、その配列をプロパティとして持つモデルにマッピングしたいことがある。

例えば以下のようなUserResponseというモデル定義する。

struct UserResponse {
    let users: [User]
}

しかし、このUserResponseCodableを適用したもうまくいかない。

struct UserResponse: Codable {
    let users: [User]
}

let response: UserResponse = try JSONDecoder().decode(UserResponse.self, from: data)

// typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead."))

カスタムデコード、エンコードメソッド

そこでDecodableEncodableのメソッドを独自に実装する。

public protocol Decodable {
    public init(from decoder: Decoder) throws
}

public protocol Encodable {
    public func encode(to encoder: Encoder) throws
}
  • Decodable
extension UserResponse: Decodable {
    init(from decoder: Decoder) throws {
        var users: [User] = []
        var unkeyedContainer = try decoder.unkeyedContainer()
        while !unkeyedContainer.isAtEnd {
            let user = try unkeyedContainer.decode(User.self)
            users.append(user)
        }
        self.init(users: users)
    }
}
  • Encodable
extension UserResponse: Encodable {
    func encode(to encoder: Encoder) throws {
        var container = encoder.unkeyedContainer()
        for user in users {
            try container.encode(user)
        }
    }
}

上記のようにDecodableEncodableを実装すればデコード、エンコードともに期待したように動く。

// decode
let response: UserResponse = try JSONDecoder().decode(UserResponse.self, from: data)

// encode
let encoded = try JSONEncoder().encode(response)
let json = String(data: encoded, encoding: .utf8)

参考


『 Swift 』Article List
Category List

Eye Catch Image
Read More

Androidに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

AWSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Bitcoinに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

CentOSに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

dockerに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

GitHubに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Goに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Javaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

JavaScriptに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Laravelに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Pythonに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Rubyに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Scalaに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Swiftに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Unityに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Vue.jsに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

Wordpressに関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。

Eye Catch Image
Read More

機械学習に関する現役のエンジニアのノウハウ・トレンドのトピックなど技術的な情報を提供しています。コード・プログラムの丁寧な解説をはじめ、初心者にもわかりやすいように写真や動画を多く使用しています。