Created
November 6, 2017 20:58
-
-
Save ilyapuchka/0edce20631d0d4a8d0d394e30c750d0e to your computer and use it in GitHub Desktop.
Codable tips suggestions
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
/* | |
Instead of using enum it's possible to use RawRepresentable struct that will give you support for "unsupported" values, | |
but will cost you excastive switches (you'll alwyas have to handle default case, which will stand for those "unsupported" values) | |
It's defenetely more code than if using optional, but might be better if it comes to unwrapping this value everywhere. | |
*/ | |
//enum System: String, Decodable { | |
// case ios, macos, tvos, watchos | |
//} | |
struct System: RawRepresentable, Decodable { | |
let rawValue: String | |
init(rawValue: String) { | |
self.rawValue = rawValue | |
} | |
static let ios = System(rawValue: "ios") | |
static let macos = System(rawValue: "macos") | |
static let tvos = System(rawValue: "tvos") | |
static let watchos = System(rawValue: "watchos") | |
} | |
final class Device: Decodable { | |
let location: Location | |
let system: System | |
} | |
let json = """ | |
{ | |
"location": { | |
"latitude": 37.3317, | |
"longitude": 122.0302 | |
}, | |
"system": "caros" | |
} | |
""" | |
let device = try JSONDecoder().decode(Device.self, from: json.data(using: .utf8)!) | |
print(device.system) // > caros |
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
protocol SafeDecodable: Decodable { | |
associatedtype T: Decodable | |
var value: T? { get } | |
} | |
public struct Safe<Base: Decodable>: SafeDecodable { | |
public let value: Base? | |
public init(from decoder: Decoder) throws { | |
do { | |
let container = try decoder.singleValueContainer() | |
self.value = try container.decode(Base.self) | |
} catch { | |
print("ERROR: \(error)") | |
// TODO: automatically send a report about a corrupted data | |
self.value = nil | |
} | |
} | |
} | |
extension JSONDecoder { | |
func decode<T>(_ type: T.Type, from data: Data) -> T.T? where T: SafeDecodable { | |
return (try? decode(type, from: data) as T)?.value | |
} | |
func decode<T>(_ type: [T].Type, from data: Data) -> [T.T] where T: SafeDecodable { | |
return (try? decode(type, from: data) as [T])?.flatMap({ $0.value }) ?? [] | |
} | |
} | |
let posts: [Post] = try JSONDecoder().decode([Safe<Post>].self, from: json.data(using: .utf8)!) | |
// will return only one Post |
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
/* | |
For approach witch schemes we can save a call to decode scheme first using some protocols and defining default Decodable | |
constructor implementation. Does not save a lot, but arguable a bit cleaner. | |
*/ | |
protocol DecodingScheme: Decodable { | |
associatedtype Entity: SchemeDecodable | |
} | |
protocol SchemeDecodable: Decodable { | |
associatedtype Scheme: DecodingScheme | |
init(from scheme: Scheme) | |
} | |
extension SchemeDecodable where Scheme.Entity == Self { | |
init(from decoder: Decoder) throws { | |
try self.init(from: Scheme(from: decoder)) | |
} | |
} | |
final class Post: SchemeDecodable { | |
let id: Id<Post> | |
let title: String | |
let webURL: URL? | |
init(from scheme: Scheme) { | |
self.id = scheme.id. | |
self.title = scheme.title | |
self.webURL = scheme.webURL?.value | |
} | |
final class Scheme: DecodingScheme { | |
typealias Entity = Post | |
let id: Id<Post> | |
let title: String | |
let webURL: Safe<URL>? | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment