Skip to content

Instantly share code, notes, and snippets.

@SergioEstevao
Created April 11, 2016 15:11
Show Gist options
  • Save SergioEstevao/92ed200851368f5bf26e2d95bcb255b9 to your computer and use it in GitHub Desktop.
Save SergioEstevao/92ed200851368f5bf26e2d95bcb255b9 to your computer and use it in GitHub Desktop.
import Foundation
/// Class for handling errors related to the parent class.
///
public enum JSONValidationErrors: ErrorType, CustomDebugStringConvertible, CustomStringConvertible {
case ExpectedDictionary
case ExpectedArray
case MissingKey(String)
case MissingIndex(Int)
case ConversionFailed(String)
case DateConversionFailed(String)
func localizedFailureReason() -> String {
switch self {
case .ExpectedDictionary:
return NSLocalizedString("Expected to find Dictionary in JSON response.",
comment: "Error message to show when reading from a JSON object and a expected dictionary is not found.")
case .ExpectedArray:
return NSLocalizedString("Expected to find Array in JSON response.",
comment: "Error message to show when reading from a JSON object and a expected array is not found.")
case MissingKey(let key):
return NSString(format:NSLocalizedString("Missing \"%@\" element in JSON response.",
comment: "Error message to show when parsing a JSON dictionary and a expected key is not found."),
"\(key)") as String
case ConversionFailed(let key):
return NSString(format:NSLocalizedString("Failed to convert object to %@ type.",
comment: "Error message to show when converstion to a expected type failed."),
"\(key)") as String
case DateConversionFailed(let key):
return NSString(format:NSLocalizedString("Failed to convert %@ to date.",
comment: "Error message to show when parsing a JSON dictionary field where a date was expected but the parsing failed."),
"\(key)") as String
case MissingIndex(let index):
return NSString(format:NSLocalizedString("Missing \"%i\" element in response array.",
comment:"Error message to show when parsing a JSON array and an expected index is not found."),
index) as String
}
}
public func convertToNSError() -> NSError {
let userInfo = [NSLocalizedFailureReasonErrorKey: self.localizedFailureReason()]
return NSError(domain: "JSONValidationErrors", code: self._code, userInfo: userInfo)
}
public var description: String { get { return localizedFailureReason() }}
public var debugDescription: String { get { return localizedFailureReason() }}
}
public class JSONObject: SequenceType {
let json: AnyObject?
public convenience init(url: NSURL) throws {
let data = try NSData(contentsOfURL: url, options: NSDataReadingOptions())
try self.init(data: data)
}
public convenience init(data: NSData) throws {
let object = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions())
self.init(json: object)
}
public init(json: AnyObject?) {
self.json = json
}
public func dictionary() throws -> [String: AnyObject] {
guard let dictionary = json as? [String: AnyObject] else {
throw JSONValidationErrors.ExpectedDictionary
}
return dictionary
}
public func array() throws -> [AnyObject] {
guard let array = json as? [AnyObject] else {
throw JSONValidationErrors.ExpectedArray
}
return array
}
public func string() throws -> String {
guard let result = json as? String else {
throw JSONValidationErrors.ConversionFailed("String")
}
return result
}
public func integer() throws -> Int {
guard let result = json as? Int else {
throw JSONValidationErrors.ConversionFailed("Int")
}
return result
}
public func double() throws -> Double {
guard let result = json as? Double else {
throw JSONValidationErrors.ConversionFailed("Double")
}
return result
}
public func bool() throws -> Bool {
guard let result = json as? Bool else {
throw JSONValidationErrors.ConversionFailed("Bool")
}
return result
}
public func null() throws -> NSNull {
guard let result = json as? NSNull else {
throw JSONValidationErrors.ConversionFailed("NSNull")
}
return result;
}
public func dictionary(key: String) throws -> JSONObject {
guard let dictionary = json as? [String: AnyObject] else {
throw JSONValidationErrors.ExpectedDictionary
}
guard let obj = dictionary[key] else {
throw JSONValidationErrors.MissingKey(key)
}
return JSONObject(json: obj)
}
public func array(index: Int) throws -> JSONObject {
guard let array = json as? [AnyObject] else {
throw JSONValidationErrors.ExpectedArray
}
guard (index >= 0) && (index < array.count) else {
throw JSONValidationErrors.MissingIndex(index)
}
let obj = array[index]
return JSONObject(json: obj)
}
public func dateWithFormatter(dateFormatter: NSDateFormatter) throws -> NSDate {
let dateString = try self.string() as String
guard let date = dateFormatter.dateFromString(dateString) else {
throw JSONValidationErrors.DateConversionFailed("")
}
return date
}
public func generate() -> IndexingGenerator<[JSONObject]> {
if let array = json as? [AnyObject] {
return array.map({ (obj) -> JSONObject in
JSONObject(json:obj)
}).generate()
}
if let dictionary = json as? [String:AnyObject] {
return dictionary.map({ (obj) -> JSONObject in
JSONObject(json:obj.0)
}).generate()
}
return Array<JSONObject>().generate()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment