-
-
Save brownsoo/4a75f1e39f9dfedba5251028ce0c9049 to your computer and use it in GitHub Desktop.
Swift Decodable With Multiple Custom Dates (https://useyourloaf.com/blog/swift-codable-with-custom-dates)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
extension DateFormatter { | |
static let iso8601Full: DateFormatter = { | |
let formatter = DateFormatter() | |
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ" | |
formatter.calendar = Calendar(identifier: .iso8601) | |
formatter.timeZone = TimeZone(secondsFromGMT: 0) | |
formatter.locale = Locale(identifier: "en_US_POSIX") | |
return formatter | |
}() | |
static let yyyyMMdd: DateFormatter = { | |
let formatter = DateFormatter() | |
formatter.dateFormat = "yyyy-MM-dd" | |
formatter.calendar = Calendar(identifier: .iso8601) | |
formatter.timeZone = TimeZone(secondsFromGMT: 0) | |
formatter.locale = Locale(identifier: "en_US_POSIX") | |
return formatter | |
}() | |
} | |
public protocol FormattedDate: Codable { | |
static var formatter: DateFormatter { get } | |
var date: Date { get } | |
init(date: Date) | |
} | |
extension FormattedDate { | |
public init(from decoder: Decoder) throws { | |
let container = try decoder.singleValueContainer() | |
let string = try container.decode(String.self) | |
guard let date = Self.formatter.date(from: string) else { | |
let debug = "Date string does not match format expected by formatter." | |
throw DecodingError.dataCorruptedError(in: container, debugDescription: debug) | |
} | |
self.init(date: date) | |
} | |
public func encode(to encoder: Encoder) throws { | |
var container = encoder.singleValueContainer() | |
let string = Self.formatter.string(from: self.date) | |
try container.encode(string) | |
} | |
} | |
struct ISO8601Date: FormattedDate { | |
static let formatter: DateFormatter = .iso8601Full | |
let date: Date | |
} | |
struct YYYMMddDate: FormattedDate { | |
static var formatter: DateFormatter = .yyyyMMdd | |
let date: Date | |
} | |
public struct RSSFeed: Codable { | |
public struct Feed: Codable { | |
public struct Podcast: Codable { | |
public let name: String | |
public let artistName: String | |
public let url: URL | |
private let _releaseDate: YYYMMddDate | |
public var releaseDate: Date { return self._releaseDate.date } | |
private enum CodingKeys: String, CodingKey { | |
case name | |
case artistName | |
case url | |
case _releaseDate = "releaseDate" | |
} | |
} | |
public let title: String | |
public let country: String | |
private let _updated: ISO8601Date | |
public var updated: Date { return self._updated.date } | |
public let podcasts: [Podcast] | |
private enum CodingKeys: String, CodingKey { | |
case title | |
case country | |
case _updated = "updated" | |
case podcasts = "results" | |
} | |
} | |
public let feed: Feed | |
} | |
public typealias Feed = RSSFeed.Feed | |
public typealias Podcast = Feed.Podcast | |
let json = """ | |
{ | |
"feed": { | |
"title":"Top Audio Podcasts", | |
"country":"gb", | |
"updated":"2017-11-16T02:02:55.000-08:00", | |
"results":[ | |
{ | |
"artistName":"BBC Radio", | |
"name":"Blue Planet II: The Podcast", | |
"releaseDate":"2017-11-12", | |
"url":"https://itunes.apple.com/gb/podcast/blue-planet-ii-the-podcast/id1296222557?mt=2" | |
}, | |
{ | |
"artistName":"Audible", | |
"name":"The Butterfly Effect with Jon Ronson", | |
"releaseDate":"2017-11-03", | |
"url":"https://itunes.apple.com/gb/podcast/the-butterfly-effect-with-jon-ronson/id1258779354?mt=2" | |
}, | |
{ | |
"artistName":"TED", | |
"name":"TED Talks Daily", | |
"releaseDate":"2017-11-16", | |
"url":"https://itunes.apple.com/gb/podcast/ted-talks-daily/id160904630?mt=2" | |
} | |
] | |
} | |
} | |
""" | |
let data = Data(json.utf8) | |
let decoder = JSONDecoder() | |
let rssFeed = try! decoder.decode(RSSFeed.self, from: data) | |
let feed = rssFeed.feed | |
print(feed.title, feed.country, feed.updated) | |
feed.podcasts.forEach { | |
print($0.name) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment