@@ -37,17 +37,22 @@ public protocol JSONDecodable {
37
37
}
38
38
39
39
/// `JSONDecodable` data response parser
40
- public struct JSONDecodableParser < Model: JSONDecodable , ErrorModel: JSONDecodable > : ErrorHandlingDataResponseSerializerProtocol
40
+ open class JSONDecodableParser < Model: JSONDecodable , ErrorModel: JSONDecodable > : ErrorHandlingDataResponseSerializerProtocol
41
41
{
42
42
public typealias SerializedError = ErrorModel
43
43
44
- public init ( ) { }
44
+ public let options : JSONSerialization . ReadingOptions
45
+
46
+ public init ( options: JSONSerialization . ReadingOptions ) {
47
+ self . options = options
48
+ }
45
49
46
50
/// A closure used by response handlers that takes a request, response, data and error and returns a result.
47
- public var serializeResponse : ( URLRequest ? , HTTPURLResponse ? , Data ? , Error ? ) -> Result < Model > {
48
- return { request, response, data, error in
49
- let json = JSON ( data: data ?? Data ( ) )
51
+ open var serializeResponse : ( URLRequest ? , HTTPURLResponse ? , Data ? , Error ? ) -> Result < Model > {
52
+ return { [ weak self] request, response, data, error in
50
53
do {
54
+ let data = data ?? Data ( )
55
+ let json = ( try ? JSON ( data: data, options: self ? . options ?? [ ] ) ) ?? JSON . null
51
56
let model = try Model . init ( json: json)
52
57
return Result . success ( model)
53
58
}
@@ -56,16 +61,15 @@ public struct JSONDecodableParser<Model: JSONDecodable, ErrorModel: JSONDecodabl
56
61
}
57
62
}
58
63
}
59
- }
60
-
61
- extension ErrorHandlingDataResponseSerializerProtocol where SerializedError : JSONDecodable
62
- {
64
+
63
65
/// A closure used by response handlers that takes a parsed result, request, response, data and error and returns a serialized error.
64
- public var serializeError : ( Result < SerializedObject > ? , URLRequest ? , HTTPURLResponse ? , Data ? , Error ? ) -> APIError < SerializedError > {
65
- return { erroredResponse, request, response, data, error in
66
+ open var serializeError : ( Result < SerializedObject > ? , URLRequest ? , HTTPURLResponse ? , Data ? , Error ? ) -> APIError < SerializedError > {
67
+ return { [ weak self ] erroredResponse, request, response, data, error in
66
68
let serializationError : Error ? = erroredResponse? . error ?? error
67
69
var error = APIError < SerializedError > ( request: request, response: response, data: data, error: serializationError)
68
- error. errorModel = try ? SerializedError . init ( json: JSON ( data: data ?? Data ( ) ) )
70
+ let data = data ?? Data ( )
71
+ let json = ( try ? JSON ( data: data, options: self ? . options ?? [ ] ) ) ?? JSON . null
72
+ error. errorModel = try ? SerializedError . init ( json: json)
69
73
return error
70
74
}
71
75
}
@@ -77,18 +81,22 @@ public enum JSONDecodableDownloadSerializationError : Error {
77
81
}
78
82
79
83
/// `JSONDecodable` download response parser
80
- public struct JSONDecodableDownloadParser < Model: JSONDecodable , ErrorModel: JSONDecodable > : ErrorHandlingDownloadResponseSerializerProtocol
84
+ open class JSONDecodableDownloadParser < Model: JSONDecodable , ErrorModel: JSONDecodable > : ErrorHandlingDownloadResponseSerializerProtocol
81
85
{
82
86
public typealias SerializedError = ErrorModel
83
87
84
- public init ( ) { }
88
+ public let options : JSONSerialization . ReadingOptions
89
+
90
+ public init ( options: JSONSerialization . ReadingOptions ) {
91
+ self . options = options
92
+ }
85
93
86
94
/// A closure used by response handlers that takes a request, response, url and error and returns a result.
87
- public var serializeResponse : ( URLRequest ? , HTTPURLResponse ? , URL ? , Error ? ) -> Result < Model > {
88
- return { request, response, url, error in
95
+ open var serializeResponse : ( URLRequest ? , HTTPURLResponse ? , URL ? , Error ? ) -> Result < Model > {
96
+ return { [ weak self ] request, response, url, error in
89
97
if let url = url, let data = try ? Data ( contentsOf: url) {
90
- let json = JSON ( data: data)
91
98
do {
99
+ let json = ( try ? JSON ( data: data, options: self ? . options ?? [ ] ) ) ?? JSON . null
92
100
let model = try Model . init ( json: json)
93
101
return Result . success ( model)
94
102
}
@@ -99,20 +107,18 @@ public struct JSONDecodableDownloadParser<Model: JSONDecodable, ErrorModel: JSON
99
107
return . failure( JSONDecodableDownloadSerializationError . failedToCreateJSONResponse)
100
108
}
101
109
}
102
- }
103
-
104
- extension ErrorHandlingDownloadResponseSerializerProtocol where SerializedError : JSONDecodable
105
- {
110
+
106
111
/// A closure used by response handlers that takes a parsed result, request, response, url and error and returns a serialized error.
107
- public var serializeError : ( Result < SerializedObject > ? , URLRequest ? , HTTPURLResponse ? , URL ? , Error ? ) -> APIError < SerializedError > {
108
- return { erroredResponse, request, response, url, error in
112
+ open var serializeError : ( Result < SerializedObject > ? , URLRequest ? , HTTPURLResponse ? , URL ? , Error ? ) -> APIError < SerializedError > {
113
+ return { [ weak self ] erroredResponse, request, response, url, error in
109
114
let serializationError : Error ? = erroredResponse? . error ?? error
110
115
var data : Data ?
111
116
if let url = url {
112
117
data = try ? Data ( contentsOf: url)
113
118
}
114
119
var error = APIError < SerializedError > ( request: request, response: response, data: data, error: serializationError)
115
- error. errorModel = try ? SerializedError . init ( json: JSON ( data: data ?? Data ( ) ) )
120
+ let json : JSON = ( try ? JSON ( data: data ?? Data ( ) , options: self ? . options ?? [ ] ) ) ?? JSON . null
121
+ error. errorModel = try ? SerializedError . init ( json: json)
116
122
return error
117
123
}
118
124
}
@@ -126,9 +132,20 @@ extension JSON : JSONDecodable {
126
132
}
127
133
}
128
134
129
- public struct JSONDecodableSerializer
135
+ // Serializer for objects, that conform to `JSONDecodable` protocol.
136
+ open class JSONDecodableSerializer
130
137
{
131
- public let tron : TRON
138
+ // `TRON` instance to be used to send requests
139
+ let tron : TRON
140
+
141
+ // Reading options to use while calling `JSONSerialization.jsonObject(withData:options:)`
142
+ open var options : JSONSerialization . ReadingOptions
143
+
144
+ // Creates `JSONDecodableSerializer` with `tron` instance to send requests, and JSON reading `options` to be passed to `JSONSerialization`.
145
+ public init ( tron: TRON , options: JSONSerialization . ReadingOptions = [ ] ) {
146
+ self . tron = tron
147
+ self . options = options
148
+ }
132
149
133
150
/**
134
151
Creates APIRequest with specified relative path and type RequestType.Default.
@@ -137,9 +154,9 @@ public struct JSONDecodableSerializer
137
154
138
155
- returns: APIRequest instance.
139
156
*/
140
- public func request< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String ) -> APIRequest < Model , ErrorModel >
157
+ open func request< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String ) -> APIRequest < Model , ErrorModel >
141
158
{
142
- return tron. request ( path, responseSerializer: JSONDecodableParser ( ) )
159
+ return tron. request ( path, responseSerializer: JSONDecodableParser ( options : options ) )
143
160
}
144
161
145
162
/**
@@ -151,9 +168,9 @@ public struct JSONDecodableSerializer
151
168
152
169
- returns: APIRequest instance.
153
170
*/
154
- public func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , fromFileAt fileURL: URL ) -> UploadAPIRequest < Model , ErrorModel >
171
+ open func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , fromFileAt fileURL: URL ) -> UploadAPIRequest < Model , ErrorModel >
155
172
{
156
- return tron. upload ( path, fromFileAt: fileURL, responseSerializer: JSONDecodableParser ( ) )
173
+ return tron. upload ( path, fromFileAt: fileURL, responseSerializer: JSONDecodableParser ( options : options ) )
157
174
}
158
175
159
176
/**
@@ -165,9 +182,9 @@ public struct JSONDecodableSerializer
165
182
166
183
- returns: APIRequest instance.
167
184
*/
168
- public func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , data: Data ) -> UploadAPIRequest < Model , ErrorModel >
185
+ open func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , data: Data ) -> UploadAPIRequest < Model , ErrorModel >
169
186
{
170
- return tron. upload ( path, data: data, responseSerializer: JSONDecodableParser ( ) )
187
+ return tron. upload ( path, data: data, responseSerializer: JSONDecodableParser ( options : options ) )
171
188
}
172
189
173
190
/**
@@ -179,9 +196,9 @@ public struct JSONDecodableSerializer
179
196
180
197
- returns: APIRequest instance.
181
198
*/
182
- public func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , from stream: InputStream ) -> UploadAPIRequest < Model , ErrorModel >
199
+ open func upload< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , from stream: InputStream ) -> UploadAPIRequest < Model , ErrorModel >
183
200
{
184
- return tron. upload ( path, from: stream, responseSerializer: JSONDecodableParser ( ) )
201
+ return tron. upload ( path, from: stream, responseSerializer: JSONDecodableParser ( options : options ) )
185
202
}
186
203
187
204
/**
@@ -193,11 +210,11 @@ public struct JSONDecodableSerializer
193
210
194
211
- returns: MultipartAPIRequest instance.
195
212
*/
196
- public func uploadMultipart< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String ,
213
+ open func uploadMultipart< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String ,
197
214
formData: @escaping ( MultipartFormData ) -> Void ) -> UploadAPIRequest < Model , ErrorModel >
198
215
{
199
216
return tron. uploadMultipart ( path,
200
- responseSerializer: JSONDecodableParser ( ) ,
217
+ responseSerializer: JSONDecodableParser ( options : options ) ,
201
218
formData: formData)
202
219
}
203
220
@@ -212,11 +229,11 @@ public struct JSONDecodableSerializer
212
229
213
230
- seealso: `Alamofire.Request.suggestedDownloadDestination(directory:domain:)` method.
214
231
*/
215
- public func download< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , to destination: @escaping DownloadRequest . DownloadFileDestination ) -> DownloadAPIRequest < Model , ErrorModel >
232
+ open func download< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , to destination: @escaping DownloadRequest . DownloadFileDestination ) -> DownloadAPIRequest < Model , ErrorModel >
216
233
{
217
234
return tron. download ( path,
218
235
to: destination,
219
- responseSerializer: JSONDecodableDownloadParser ( ) )
236
+ responseSerializer: JSONDecodableDownloadParser ( options : options ) )
220
237
}
221
238
222
239
/**
@@ -232,18 +249,27 @@ public struct JSONDecodableSerializer
232
249
233
250
- seealso: `Alamofire.Request.suggestedDownloadDestination(directory:domain:)` method.
234
251
*/
235
- public func download< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , to destination: @escaping DownloadRequest . DownloadFileDestination , resumingFrom: Data ) -> DownloadAPIRequest < Model , ErrorModel >
252
+ open func download< Model: JSONDecodable , ErrorModel: JSONDecodable > ( _ path: String , to destination: @escaping DownloadRequest . DownloadFileDestination , resumingFrom: Data ) -> DownloadAPIRequest < Model , ErrorModel >
236
253
{
237
- return tron. download ( path, to: destination, resumingFrom: resumingFrom, responseSerializer: JSONDecodableDownloadParser ( ) )
254
+ return tron. download ( path, to: destination, resumingFrom: resumingFrom, responseSerializer: JSONDecodableDownloadParser ( options : options ) )
238
255
}
239
256
}
240
257
241
258
extension TRON {
259
+ // Creates `JSONDecodableSerializer` with current `TRON` instance.
242
260
open var swiftyJSON : JSONDecodableSerializer {
243
261
return JSONDecodableSerializer ( tron: self )
244
262
}
263
+
264
+ // Creates `CodableSerializer` with current `TRON` instance and specific `options` for `JSONSerialization`.
265
+ open func swiftyJSON( readingOptions options: JSONSerialization . ReadingOptions ) -> JSONDecodableSerializer {
266
+ return JSONDecodableSerializer ( tron: self , options: options)
267
+ }
245
268
}
246
269
270
+ // This approach is bad, because it allows any JSONDecodable.Type to be created, not just specific one.
271
+ // See https://github.com/MLSDev/TRON/issues/17 for details
272
+
247
273
//extension Array : JSONDecodable {
248
274
// public init(json: JSON) {
249
275
// self.init(json.arrayValue.flatMap {
0 commit comments