在 URLRequest 中使用 Combine 将对象编码为 httpBody
Using Combine to encode object to httpBody in URLRequest
有没有办法使用 Combine 将对象编码为 urlRequest.httpBody
或 return 解码为具有特定错误类型的 AnyPublisher 的错误。
我无法让它工作,而且似乎没有使用 combine 编码对象的代码示例。必须强制将编码错误转换为 AnyPublisher 似乎不正确/不安全。
谢谢
func create(object: ExampleObject, token: Token) -> AnyPublisher<ExampleObject, API.Error> {
let url = API.EndPoint.players.url
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
do {
// is there a safe combine way to encode this
urlRequest.httpBody = try JSONEncoder().encode(object)
} catch {
// Is there a better way to handle this
return error as! AnyPublisher<ExampleObject, API.Error>
}
return session
.dataTaskPublisher(for: urlRequest)
.map(\.data)
.decode(type: ExampleObject.self, decoder: JSONDecoder())
.mapError { error in
switch error {
case is URLError:
return API.Error.addressUnreachable
default:
return API.Error.invalidResponse
}
}
.eraseToAnyPublisher()
}
没有您的 API.Error
枚举,所以我创建了一个简单的枚举,例如
enum APIError: Error {
case encode(EncodingError)
case request(URLError)
case decode(DecodingError)
case unknown
}
func create<ExampleObject>(object: ExampleObject, token: String) -> AnyPublisher<ExampleObject, APIError> where ExampleObject: Codable {
return Just(object)
.encode(encoder: JSONEncoder())
.mapError { error -> APIError in
if let encodingError = error as? EncodingError {
return .encode(encodingError)
} else {
return .unknown
}
}
.map { data -> URLRequest in
var urlRequest = URLRequest(url: API.EndPoint.players.url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
urlRequest.httpBody = data
return urlRequest
}.flatMap {
URLSession.shared.dataTaskPublisher(for: [=11=])
.mapError(APIError.request)
.map(\.data)
.decode(type: ExampleObject.self, decoder: JSONDecoder())
.mapError { error -> APIError in
if let decodingError = error as? DecodingError {
return .decode(decodingError)
} else {
return .unknown
}
}
}
.eraseToAnyPublisher()
}
有没有办法使用 Combine 将对象编码为 urlRequest.httpBody
或 return 解码为具有特定错误类型的 AnyPublisher 的错误。
我无法让它工作,而且似乎没有使用 combine 编码对象的代码示例。必须强制将编码错误转换为 AnyPublisher 似乎不正确/不安全。
谢谢
func create(object: ExampleObject, token: Token) -> AnyPublisher<ExampleObject, API.Error> {
let url = API.EndPoint.players.url
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
do {
// is there a safe combine way to encode this
urlRequest.httpBody = try JSONEncoder().encode(object)
} catch {
// Is there a better way to handle this
return error as! AnyPublisher<ExampleObject, API.Error>
}
return session
.dataTaskPublisher(for: urlRequest)
.map(\.data)
.decode(type: ExampleObject.self, decoder: JSONDecoder())
.mapError { error in
switch error {
case is URLError:
return API.Error.addressUnreachable
default:
return API.Error.invalidResponse
}
}
.eraseToAnyPublisher()
}
没有您的 API.Error
枚举,所以我创建了一个简单的枚举,例如
enum APIError: Error {
case encode(EncodingError)
case request(URLError)
case decode(DecodingError)
case unknown
}
func create<ExampleObject>(object: ExampleObject, token: String) -> AnyPublisher<ExampleObject, APIError> where ExampleObject: Codable {
return Just(object)
.encode(encoder: JSONEncoder())
.mapError { error -> APIError in
if let encodingError = error as? EncodingError {
return .encode(encodingError)
} else {
return .unknown
}
}
.map { data -> URLRequest in
var urlRequest = URLRequest(url: API.EndPoint.players.url)
urlRequest.httpMethod = "POST"
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
urlRequest.httpBody = data
return urlRequest
}.flatMap {
URLSession.shared.dataTaskPublisher(for: [=11=])
.mapError(APIError.request)
.map(\.data)
.decode(type: ExampleObject.self, decoder: JSONDecoder())
.mapError { error -> APIError in
if let decodingError = error as? DecodingError {
return .decode(decodingError)
} else {
return .unknown
}
}
}
.eraseToAnyPublisher()
}