Skip to content

Instantly share code, notes, and snippets.

@cjnevin
Last active November 29, 2017 01:05
Show Gist options
  • Save cjnevin/44a4736e7a2232b12b6b0c235ce8ac3d to your computer and use it in GitHub Desktop.
Save cjnevin/44a4736e7a2232b12b6b0c235ce8ac3d to your computer and use it in GitHub Desktop.
JsonParser
import Foundation
protocol JsonDeserializable {
init(json: Any) throws
}
struct JsonParser {
enum Error: Swift.Error {
case invalidKey(String)
case invalidJson
}
private let json: [String: Any]
init(json: Any) throws {
guard let json = json as? [String: Any] else {
throw Error.invalidJson
}
self.json = json
}
func parse<T: RawRepresentable, U>(_ key: T) throws
-> U where T.RawValue == String {
guard let value = json[key.rawValue] as? U else {
throw Error.invalidKey(key.rawValue)
}
return value
}
func parseEnum<T: RawRepresentable, U: RawRepresentable>(_ key: T) throws
-> U where T.RawValue == String, U.RawValue == String {
guard let rawValue = json[key.rawValue] as? String else {
throw Error.invalidKey(key.rawValue)
}
guard let value = U(rawValue: rawValue) else {
throw Error.invalidKey(key.rawValue)
}
return value
}
func parseOptional<T: RawRepresentable, U>(_ key: T)
-> U? where T.RawValue == String {
return json[key.rawValue] as? U
}
func parseObject<T: RawRepresentable, U: JsonDeserializable>(_ key: T) throws
-> U where T.RawValue == String {
guard let objectJson = json[key.rawValue] as? [String: Any] else {
throw Error.invalidKey(key.rawValue)
}
return try U.init(json: objectJson)
}
func parseObjectArray<T: RawRepresentable, U: JsonDeserializable>(_ key: T, minCount: Int = 0) throws
-> [U] where T.RawValue == String {
guard let array = json[key.rawValue] as? [[String: Any]] else {
throw Error.invalidKey(key.rawValue)
}
if array.count < minCount {
throw Error.invalidKey(key.rawValue)
}
return try array.map { try U.init(json: $0) }
}
func parseObjects<T: RawRepresentable & Equatable, U: JsonDeserializable>
(forKeys keys: T..., required: [T] = []) throws
-> [U] where T.RawValue == String {
var buffer: [U] = []
for key in keys {
guard let objectJson = json[key.rawValue] as? [String: Any],
let object = try? U.init(json: objectJson) else {
if required.contains(key) {
throw Error.invalidKey(key.rawValue)
} else {
continue
}
}
buffer.append(object)
}
return buffer
}
func parseObjectOptional<T: RawRepresentable, U: JsonDeserializable>(_ key: T)
-> U? where T.RawValue == String {
guard let objectJson = json[key.rawValue] as? [String: Any] else {
return nil
}
return try? U.init(json: objectJson)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment