次のようなStructを例にencoder/decoderを実装します。
Post.swift
struct Post {
var id: String
var text: String
var createdAt: Date
init(id: String, text: String, createdAt: Date) {
self.id = id
self.text = text
self.createdAt = createdAt
}
}
Swiftでは、Date
型の変数を単純にencodeするとtimeIntervalSinceReferenceDate: TimeInterval
になります。
そのため、データベース等に保存する際はISO8601形式などの文字列に変換すると便利です。
Post.swift
extension Post: Codable {
enum CodingKeys: String, CodingKey {
case id
case text = "text_data"
case createdAt
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(text, forKey: .text)
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: createdAt)
try container.encode(dateString, forKey: .createdAt)
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.text = try container.decode(String.self, forKey: .text)
let dateString = try container.decode(String.self, forKey: .createdAt)
let formatter = ISO8601DateFormatter()
if let date = formatter.date(from: dateString) {
self.createdAt = date
} else {
throw DecodingError.dataCorruptedError(forKey: .createdAt, in: container, debugDescription: "")
}
}
}
実際に使ってみましょう。
まずはencodeです。
func addPost() {
let post = Post(id: "aaa", text: "Hello!", createdAt: Date())
let encoded = try! JSONEncoder().encode(post)
do {
guard let jsonObject = try JSONSerialization.jsonObject(with: encoded, options: []) as? [String: Any] else { return }
print(jsonObject)
} catch {}
}
["createdAt": 2024-07-09T15:30:26Z, "text_data": Hello!, "id": aaa]
ちゃんとencodeできました。
次に、decodeもやってみましょう。
let jsonData = """
{
"id": "aaa",
"createdAt": "2024-07-09T15:02:51Z",
"text_data": "Hello!"
}
"""
func fetchPost(){
guard let data = jsonData.data(using: .utf8) else { return }
do {
let decoded = try JSONDecoder().decode(Post.self, from: data)
print(decoded)
} catch {}
}
Post(id: "aaa", text: "Hello!", createdAt: 2024-07-09 15:02:51 +0000)
受け取ったString
型の日付をdecodeしてDate
型にすることができました。