|
8 | 8 |
|
9 | 9 | import Foundation |
10 | 10 | import Siesta |
11 | | -import SwiftyJSON |
12 | 11 |
|
13 | 12 | // MARK: - Initialization and configuration |
14 | 13 |
|
@@ -36,53 +35,45 @@ public final class AppleAPIClient { |
36 | 35 | } |
37 | 36 | } |
38 | 37 |
|
39 | | - private let jsonParser = ResponseContentTransformer { JSON($0.content as AnyObject) } |
| 38 | + |
40 | 39 |
|
41 | 40 | private func configureService() { |
42 | 41 | service.configure("**") { config in |
43 | | - config.pipeline[.parsing].add(self.jsonParser, contentTypes: ["*/json"]) |
| 42 | + // Parsing & Transformation is done using Codable, no need to let Siesta do the parsing |
| 43 | + config.pipeline[.parsing].removeTransformers() |
44 | 44 | } |
45 | 45 |
|
46 | | - service.configureTransformer(environment.newsPath) { [weak self] (entity: Entity<JSON>) throws -> [NewsItem]? in |
47 | | - guard let newsItemsJson = entity.content["items"].array else { |
48 | | - throw APIError.adapter |
| 46 | + let decoder = JSONDecoder() |
| 47 | + decoder.dateDecodingStrategy = .formatted(.confCoreFormatter) |
| 48 | + |
| 49 | + service.configureTransformer(environment.newsPath) { (entity: Entity<Data>) throws -> [NewsItem]? in |
| 50 | + struct NewsItemWrapper: Decodable { |
| 51 | + let items: FailableItemArrayWrapper<NewsItem> |
49 | 52 | } |
50 | 53 |
|
51 | | - return try self?.failableAdaptCollection(newsItemsJson, using: NewsItemsJSONAdapter()) |
| 54 | + let result = try decoder.decode(NewsItemWrapper.self, from: entity.content).items.items |
| 55 | + return result |
52 | 56 | } |
53 | 57 |
|
54 | | - service.configureTransformer(environment.featuredSectionsPath) { [weak self] (entity: Entity<JSON>) throws -> [FeaturedSection]? in |
55 | | - guard let sectionsJSON = entity.content["sections"].array else { |
56 | | - throw APIError.adapter |
| 58 | + service.configureTransformer(environment.featuredSectionsPath) { (entity: Entity<Data>) throws -> [FeaturedSection]? in |
| 59 | + struct FeaturedContentWrapper: Decodable { |
| 60 | + let sections: FailableItemArrayWrapper<FeaturedSection> |
57 | 61 | } |
58 | 62 |
|
59 | | - return try self?.failableAdaptCollection(sectionsJSON, using: FeaturedSectionsJSONAdapter()) |
| 63 | + let result = try decoder.decode(FeaturedContentWrapper.self, from: entity.content).sections.items |
| 64 | + return result |
60 | 65 | } |
61 | 66 |
|
62 | | - service.configureTransformer(environment.sessionsPath) { [weak self] (entity: Entity<JSON>) throws -> ContentsResponse? in |
63 | | - return try self?.failableAdapt(entity.content, using: ContentsResponseAdapter()) |
| 67 | + service.configureTransformer(environment.sessionsPath) { (entity: Entity<Data>) throws -> ContentsResponse? in |
| 68 | + return try decoder.decode(ContentsResponse.self, from: entity.content) |
64 | 69 | } |
65 | 70 |
|
66 | | - service.configureTransformer(environment.videosPath) { [weak self] (entity: Entity<JSON>) throws -> SessionsResponse? in |
67 | | - return try self?.failableAdapt(entity.content, using: SessionsResponseAdapter()) |
| 71 | + service.configureTransformer(environment.videosPath) { (entity: Entity<Data>) throws -> SessionsResponse? in |
| 72 | + return try decoder.decode(SessionsResponse.self, from: entity.content) |
68 | 73 | } |
69 | 74 |
|
70 | | - service.configureTransformer(environment.liveVideosPath) { [weak self] (entity: Entity<JSON>) throws -> [SessionAsset]? in |
71 | | - guard let sessionsDict = entity.content["live_sessions"].dictionary else { |
72 | | - throw APIError.adapter |
73 | | - } |
74 | | - |
75 | | - let sessionsArray = sessionsDict.compactMap { key, value -> JSON? in |
76 | | - guard let id = JSON.init(rawValue: key) else { return nil } |
77 | | - |
78 | | - var v = value |
79 | | - |
80 | | - v["sessionId"] = id |
81 | | - |
82 | | - return v |
83 | | - } |
84 | | - |
85 | | - return try self?.failableAdaptCollection(sessionsArray, using: LiveVideosAdapter()) |
| 75 | + service.configureTransformer(environment.liveVideosPath) { (entity: Entity<Data>) throws -> [SessionAsset]? in |
| 76 | + return try decoder.decode(LiveVideosWrapper.self, from: entity.content).liveAssets |
86 | 77 | } |
87 | 78 | } |
88 | 79 |
|
@@ -199,30 +190,6 @@ public final class AppleAPIClient { |
199 | 190 |
|
200 | 191 | extension AppleAPIClient { |
201 | 192 |
|
202 | | - /// Convenience method to use a model adapter as a method that returns the model(s) or throws an error |
203 | | - fileprivate func failableAdapt<A: Adapter, T>(_ input: JSON, using adapter: A) throws -> T where A.InputType == JSON, A.OutputType == T { |
204 | | - let result = adapter.adapt(input) |
205 | | - |
206 | | - switch result { |
207 | | - case let .error(error): |
208 | | - throw error |
209 | | - case let .success(output): |
210 | | - return output |
211 | | - } |
212 | | - } |
213 | | - |
214 | | - /// Convenience method to use a model adapter as a method that returns the model(s) or throws an error |
215 | | - fileprivate func failableAdaptCollection<A: Adapter, T>(_ input: [JSON], using adapter: A) throws -> [T] where A.InputType == JSON, A.OutputType == T { |
216 | | - let result = adapter.adapt(input) |
217 | | - |
218 | | - switch result { |
219 | | - case let .error(error): |
220 | | - throw error |
221 | | - case let .success(output): |
222 | | - return output |
223 | | - } |
224 | | - } |
225 | | - |
226 | 193 | fileprivate func process<M>(_ resource: Resource, event: ResourceEvent, with completion: @escaping (Result<M, APIError>) -> Void) { |
227 | 194 | switch event { |
228 | 195 | case .error: |
|
0 commit comments