Skip to content

Commit

Permalink
Merge pull request #49 from freshOS/dateDecodingStrategy
Browse files Browse the repository at this point in the history
Makes JSONDecoder configurable
  • Loading branch information
s4cha authored Apr 28, 2022
2 parents 9980135 + 4ffbaff commit 82f49fa
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 101 deletions.
40 changes: 20 additions & 20 deletions Sources/Networking/Calls/NetworkingClient+Decodable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return get(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -25,7 +25,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<T, Error> where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return get(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -34,7 +34,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return post(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -45,7 +45,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<T, Error> where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return post(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -54,7 +54,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return put(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -65,7 +65,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<T, Error> where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return put(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -74,7 +74,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return patch(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -85,7 +85,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<T, Error> where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return patch(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -94,7 +94,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return delete(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -105,7 +105,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<T, Error> where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return delete(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -118,7 +118,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) async throws -> T {
let json: Any = try await get(route, params: params)
let model:T = try NetworkingParser().toModel(json, keypath: keypath)
let model:T = try self.toModel(json, keypath: keypath)
return model
}

Expand All @@ -127,66 +127,66 @@ public extension NetworkingClient {
keypath: String? = nil) async throws -> T where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
let json: Any = try await get(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func post<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T {
let json: Any = try await post(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func post<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
let json: Any = try await post(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func put<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T {
let json: Any = try await put(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func put<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
let json: Any = try await put(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func patch<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T {
let json: Any = try await patch(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func patch<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
let json: Any = try await patch(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func delete<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T {
let json: Any = try await delete(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}

func delete<T: Decodable>(_ route: String,
params: Params = Params(),
keypath: String? = nil) async throws -> T where T: Collection {
let keypath = keypath ?? defaultCollectionParsingKeyPath
let json: Any = try await delete(route, params: params)
return try NetworkingParser().toModel(json, keypath: keypath)
return try self.toModel(json, keypath: keypath)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return get(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -31,7 +31,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<[T], Error> {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return get(route, params: params)
.tryMap { json -> [T] in try NetworkingParser().toModels(json, keypath: keypath) }
.tryMap { json -> [T] in try self.toModels(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -40,7 +40,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return post(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -51,7 +51,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<[T], Error> {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return post(route, params: params)
.tryMap { json -> [T] in try NetworkingParser().toModels(json, keypath: keypath) }
.tryMap { json -> [T] in try self.toModels(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -60,7 +60,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return put(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -72,7 +72,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<[T], Error> {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return put(route, params: params)
.tryMap { json -> [T] in try NetworkingParser().toModels(json, keypath: keypath) }
.tryMap { json -> [T] in try self.toModels(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -81,7 +81,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return patch(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -92,7 +92,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<[T], Error> {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return patch(route, params: params)
.tryMap { json -> [T] in try NetworkingParser().toModels(json, keypath: keypath) }
.tryMap { json -> [T] in try self.toModels(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -101,7 +101,7 @@ public extension NetworkingClient {
params: Params = Params(),
keypath: String? = nil) -> AnyPublisher<T, Error> {
return delete(route, params: params)
.tryMap { json -> T in try NetworkingParser().toModel(json, keypath: keypath) }
.tryMap { json -> T in try self.toModel(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand All @@ -112,7 +112,7 @@ public extension NetworkingClient {
keypath: String? = nil) -> AnyPublisher<[T], Error> {
let keypath = keypath ?? defaultCollectionParsingKeyPath
return delete(route, params: params)
.tryMap { json -> [T] in try NetworkingParser().toModels(json, keypath: keypath) }
.tryMap { json -> [T] in try self.toModels(json, keypath: keypath) }
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
Expand Down
58 changes: 58 additions & 0 deletions Sources/Networking/NetworkingClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public class NetworkingClient {
public var timeout: TimeInterval?
public var sessionConfiguration = URLSessionConfiguration.default
public var requestRetrier: NetworkRequestRetrier?
public var jsonDecoderFactory: (() -> JSONDecoder)?

/**
Prints network calls to the console.
Expand All @@ -32,5 +33,62 @@ public class NetworkingClient {
self.baseURL = baseURL
self.timeout = timeout
}

public func toModel<T: NetworkingJSONDecodable>(_ json: Any, keypath: String? = nil) throws -> T {
do {
let data = resourceData(from: json, keypath: keypath)
return try T.decode(data)
} catch (let error) {
throw error
}
}

public func toModel<T: Decodable>(_ json: Any, keypath: String? = nil) throws -> T {
do {
let jsonObject = resourceData(from: json, keypath: keypath)
let decoder = jsonDecoderFactory?() ?? JSONDecoder()
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
let model = try decoder.decode(T.self, from: data)
return model
} catch (let error) {
throw error
}
}

public func toModels<T: NetworkingJSONDecodable>(_ json: Any, keypath: String? = nil) throws -> [T] {
do {
guard let array = resourceData(from: json, keypath: keypath) as? [Any] else {
return [T]()
}
return try array.map {
try T.decode($0)
}.compactMap { $0 }
} catch (let error) {
throw error
}
}

public func toModels<T: Decodable>(_ json: Any, keypath: String? = nil) throws -> [T] {
do {
guard let array = resourceData(from: json, keypath: keypath) as? [Any] else {
return [T]()
}
return try array.map { jsonObject in
let decoder = jsonDecoderFactory?() ?? JSONDecoder()
let data = try JSONSerialization.data(withJSONObject: jsonObject, options: [])
let model = try decoder.decode(T.self, from: data)
return model
}.compactMap { $0 }
} catch (let error) {
throw error
}
}

private func resourceData(from json: Any, keypath: String?) -> Any {
if let keypath = keypath, !keypath.isEmpty, let dic = json as? [String: Any], let val = dic[keypath] {
return val is NSNull ? json : val
}
return json
}
}

Loading

0 comments on commit 82f49fa

Please sign in to comment.