-
Notifications
You must be signed in to change notification settings - Fork 2
/
ArgoRequest.swift
143 lines (118 loc) · 6.63 KB
/
ArgoRequest.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//
// ArgoRequest.swift
// Pods
//
// Created by Guillermo Chiacchio on 6/24/15.
//
//
import Foundation
import Alamofire
import Argo
/// Constant defining the domain to be set in NSError instances.
public let AlamoArgoErrorDomain = "AlamoArgo.err"
// MARK: - responseDecodable
/**
Alamofire.Request extensions to parse a JSON response into an object using Argo framework
*/
extension Request {
/**
JSON Response serializer with keyPath
- parameter request: The `NSURLRequest`
- parameter response: The `NSHTTPURLResponse` obtained
- parameter data: Raw data in the response
- parameter keyPath: KeyPath to locate in the parsed JSON.
- returns: Tuple representing the parsed result starting from **keyPath**, if present, and the corresponding error in case of any.
*/
public static func jsonResponseSerializer(keyPath: String? = nil) -> ResponseSerializer<AnyObject, NSError> {
return ResponseSerializer { request, response, data, error in
guard error == nil else { return .Failure(error!) }
guard let validData = data else {
let failureReason = "Data could not be serialized. Input data was nil."
let error = Error.errorWithCode(.DataSerializationFailed, failureReason: failureReason)
return .Failure(error)
}
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let result: Result<AnyObject, NSError> = JSONSerializer.serializeResponse(request, response, validData, error)
var jsonForPath: AnyObject? = result.value
if let myError = result.error {
return .Failure(myError)
}
if let kp = keyPath {
jsonForPath = result.value?.valueForKeyPath(kp)
if let jsonResult = jsonForPath {
return .Success(jsonResult)
} else {
return .Failure(NSError(domain: AlamoArgoErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey:"No such path"]))
}
}
if let jsonResult = jsonForPath {
return .Success(jsonResult)
}
return .Failure(NSError(domain: AlamoArgoErrorDomain, code: 1, userInfo: [:]))
}
}
/**
Response handler called with the `Decoded` object, or error. This is the **single object** handler
- parameter queue: The queue on which the completion handler is dispatched.
- parameter keyPath: KeyPath in JSON response where to start parsing to create the `Decodable` object
- parameter completionHandler: A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the `Decodable` object, if one could be created from the URL response and data, and any error produced while creating the `Decodable` object.
- returns: The `Request` instance.
*/
public func responseDecodable<T: Decodable where T == T.DecodedType>(queue queue: dispatch_queue_t? = nil, keyPath: String? = nil, completionHandler: Response<T, NSError> -> Void) -> Self {
let serializer = ResponseSerializer<T, NSError> { request, response, data, error in
if let myError = error {
return Result<T, NSError>.Failure(myError)
}
let result: Result<AnyObject, NSError> = Request.jsonResponseSerializer(keyPath).serializeResponse(request, response, data, error)
if let myError = error {
return Result<T, NSError>.Failure(myError)
}
if let myError = result.error {
return Result<T, NSError>.Failure(myError)
}
if let json: AnyObject = result.value {
let obj: Decoded<T> = decode(json)
switch (obj) {
case let .Success(value):
return Result<T, NSError>.Success(value)
default:
return Result<T, NSError>.Failure(NSError(domain: AlamoArgoErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey:obj.description]))
}
}
return Result<T, NSError>.Failure(NSError(domain: AlamoArgoErrorDomain, code: -1, userInfo: nil))
}
return response(queue: queue, responseSerializer: serializer, completionHandler: completionHandler)
}
/**
Response handler called with the `Decoded` object, or error. This is the **array** handler
- parameter queue: The queue on which the completion handler is dispatched.
- parameter keyPath: KeyPath in JSON response where to start parsing to create the `Decodable` object
- parameter completionHandler: A closure to be executed once the request has finished. The closure takes 4 arguments: the URL request, the URL response, if one was received, the `Decodable` object, if one could be created from the URL response and data, and any error produced while creating the `Decodable` object.
- returns: The `Request` instance.
*/
public func responseDecodable<T: Decodable where T == T.DecodedType>(queue queue: dispatch_queue_t? = nil, keyPath: String? = nil, completionHandler: Response<[T], NSError> -> Void) -> Self {
let serializer = ResponseSerializer<[T], NSError> { request, response, data, error in
if let myError = error {
return Result<[T], NSError>.Failure(myError)
}
let result: Result<AnyObject, NSError> = Request.jsonResponseSerializer(keyPath).serializeResponse(request, response, data, error)
if let myError = error {
return Result<[T], NSError>.Failure(myError)
}
if let myError = result.error {
return Result<[T], NSError>.Failure(myError)
}
if let json: AnyObject = result.value {
let obj: Decoded<[T]> = decode(json)
switch (obj) {
case let .Success(value):
return Result<[T], NSError>.Success(value)
default:
return Result<[T], NSError>.Failure(NSError(domain: AlamoArgoErrorDomain, code: 1, userInfo: [NSLocalizedDescriptionKey:obj.description]))
}
}
return Result<[T], NSError>.Failure(NSError(domain: AlamoArgoErrorDomain, code: -1, userInfo: nil))
}
return response(queue: queue, responseSerializer: serializer, completionHandler: completionHandler)
}
}