Project Setup
This commit is contained in:
+311
@@ -0,0 +1,311 @@
|
||||
//
|
||||
// Request.swift
|
||||
// AlamofireObjectMapper
|
||||
//
|
||||
// Created by Tristan Himmelman on 2015-04-30.
|
||||
//
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2014-2015 Tristan Himmelman
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
import Foundation
|
||||
import Alamofire
|
||||
import ObjectMapper
|
||||
|
||||
extension DataRequest {
|
||||
|
||||
enum ErrorCode: Int {
|
||||
case noData = 1
|
||||
case dataSerializationFailed = 2
|
||||
}
|
||||
|
||||
/// Utility function for extracting JSON from response
|
||||
internal static func processResponse(request: URLRequest?, response: HTTPURLResponse?, data: Data?, keyPath: String?) -> Any? {
|
||||
|
||||
let jsonResponseSerializer = JSONResponseSerializer(options: .allowFragments)
|
||||
if let result = try? jsonResponseSerializer.serialize(request: request, response: response, data: data, error: nil) {
|
||||
|
||||
let JSON: Any?
|
||||
if let keyPath = keyPath , keyPath.isEmpty == false {
|
||||
JSON = (result as AnyObject?)?.value(forKeyPath: keyPath)
|
||||
} else {
|
||||
JSON = result
|
||||
}
|
||||
|
||||
return JSON
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
internal static func newError(_ code: ErrorCode, failureReason: String) -> NSError {
|
||||
let errorDomain = "com.alamofireobjectmapper.error"
|
||||
|
||||
let userInfo = [NSLocalizedFailureReasonErrorKey: failureReason]
|
||||
let returnError = NSError(domain: errorDomain, code: code.rawValue, userInfo: userInfo)
|
||||
|
||||
return returnError
|
||||
}
|
||||
|
||||
/// Utility function for checking for errors in response
|
||||
internal static func checkResponseForError(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) -> Error? {
|
||||
if let error = error {
|
||||
return error
|
||||
}
|
||||
guard let _ = data else {
|
||||
let failureReason = "Data could not be serialized. Input data was nil."
|
||||
let error = newError(.noData, failureReason: failureReason)
|
||||
return error
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
/// BaseMappable Object Serializer
|
||||
public static func ObjectMapperSerializer<T: BaseMappable>(_ keyPath: String?, mapToObject object: T? = nil, context: MapContext? = nil) -> MappableResponseSerializer<T> {
|
||||
|
||||
return MappableResponseSerializer(keyPath, mapToObject: object, context: context, serializeCallback: {
|
||||
request, response, data, error in
|
||||
|
||||
let JSONObject = processResponse(request: request, response: response, data: data, keyPath: keyPath)
|
||||
|
||||
if let object = object {
|
||||
_ = Mapper<T>(context: context, shouldIncludeNilValues: false).map(JSONObject: JSONObject, toObject: object)
|
||||
return object
|
||||
} else if let parsedObject = Mapper<T>(context: context, shouldIncludeNilValues: false).map(JSONObject: JSONObject){
|
||||
return parsedObject
|
||||
}
|
||||
|
||||
let failureReason = "ObjectMapper failed to serialize response."
|
||||
throw AFError.responseSerializationFailed(reason: .decodingFailed(error: newError(.dataSerializationFailed, failureReason: failureReason)))
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
/// ImmutableMappable Array Serializer
|
||||
public static func ObjectMapperImmutableSerializer<T: ImmutableMappable>(_ keyPath: String?, context: MapContext? = nil) -> MappableResponseSerializer<T> {
|
||||
|
||||
return MappableResponseSerializer(keyPath, context: context, serializeCallback: {
|
||||
request, response, data, error in
|
||||
|
||||
let JSONObject = processResponse(request: request, response: response, data: data, keyPath: keyPath)
|
||||
|
||||
if let JSONObject = JSONObject,
|
||||
let parsedObject = (try? Mapper<T>(context: context, shouldIncludeNilValues: false).map(JSONObject: JSONObject) as T) {
|
||||
return parsedObject
|
||||
} else {
|
||||
let failureReason = "ObjectMapper failed to serialize response."
|
||||
throw AFError.responseSerializationFailed(reason: .decodingFailed(error: newError(.dataSerializationFailed, failureReason: failureReason)))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a handler to be called once the request has finished.
|
||||
|
||||
- parameter queue: The queue on which the completion handler is dispatched.
|
||||
- parameter keyPath: The key path where object mapping should be performed
|
||||
- parameter object: An object to perform the mapping on to
|
||||
- parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
|
||||
|
||||
- returns: The request.
|
||||
*/
|
||||
@discardableResult
|
||||
public func responseObject<T: BaseMappable>(queue: DispatchQueue = .main, keyPath: String? = nil, mapToObject object: T? = nil, context: MapContext? = nil, completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
|
||||
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperSerializer(keyPath, mapToObject: object, context: context), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public func responseObject<T: ImmutableMappable>(queue: DispatchQueue = .main, keyPath: String? = nil, mapToObject object: T? = nil, context: MapContext? = nil, completionHandler: @escaping (AFDataResponse<T>) -> Void) -> Self {
|
||||
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperImmutableSerializer(keyPath, context: context), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
/// BaseMappable Array Serializer
|
||||
public static func ObjectMapperArraySerializer<T: BaseMappable>(_ keyPath: String?, context: MapContext? = nil) -> MappableArrayResponseSerializer<T> {
|
||||
|
||||
|
||||
|
||||
return MappableArrayResponseSerializer(keyPath, context: context, serializeCallback: {
|
||||
request, response, data, error in
|
||||
|
||||
let JSONObject = processResponse(request: request, response: response, data: data, keyPath: keyPath)
|
||||
|
||||
if let parsedObject = Mapper<T>(context: context, shouldIncludeNilValues: false).mapArray(JSONObject: JSONObject){
|
||||
return parsedObject
|
||||
}
|
||||
|
||||
let failureReason = "ObjectMapper failed to serialize response."
|
||||
throw AFError.responseSerializationFailed(reason: .decodingFailed(error: newError(.dataSerializationFailed, failureReason: failureReason)))
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/// ImmutableMappable Array Serializer
|
||||
public static func ObjectMapperImmutableArraySerializer<T: ImmutableMappable>(_ keyPath: String?, context: MapContext? = nil) -> MappableArrayResponseSerializer<T> {
|
||||
return MappableArrayResponseSerializer(keyPath, context: context, serializeCallback: {
|
||||
request, response, data, error in
|
||||
|
||||
if let JSONObject = processResponse(request: request, response: response, data: data, keyPath: keyPath){
|
||||
|
||||
if let parsedObject = try? Mapper<T>(context: context, shouldIncludeNilValues: false).mapArray(JSONObject: JSONObject) as [T] {
|
||||
return parsedObject
|
||||
}
|
||||
}
|
||||
|
||||
let failureReason = "ObjectMapper failed to serialize response."
|
||||
throw AFError.responseSerializationFailed(reason: .decodingFailed(error: newError(.dataSerializationFailed, failureReason: failureReason)))
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a handler to be called once the request has finished. T: BaseMappable
|
||||
|
||||
- parameter queue: The queue on which the completion handler is dispatched.
|
||||
- parameter keyPath: The key path where object mapping should be performed
|
||||
- parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
|
||||
|
||||
- returns: The request.
|
||||
*/
|
||||
@discardableResult
|
||||
public func responseArray<T: BaseMappable>(queue: DispatchQueue = .main, keyPath: String? = nil, context: MapContext? = nil, completionHandler: @escaping (AFDataResponse<[T]>) -> Void) -> Self {
|
||||
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperArraySerializer(keyPath, context: context), completionHandler: completionHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
Adds a handler to be called once the request has finished. T: ImmutableMappable
|
||||
|
||||
- parameter queue: The queue on which the completion handler is dispatched.
|
||||
- parameter keyPath: The key path where object mapping should be performed
|
||||
- parameter completionHandler: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
|
||||
|
||||
- returns: The request.
|
||||
*/
|
||||
@discardableResult
|
||||
public func responseArray<T: ImmutableMappable>(queue: DispatchQueue = .main, keyPath: String? = nil, context: MapContext? = nil, completionHandler: @escaping (AFDataResponse<[T]>) -> Void) -> Self {
|
||||
return response(queue: queue, responseSerializer: DataRequest.ObjectMapperImmutableArraySerializer(keyPath, context: context), completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
|
||||
public final class MappableResponseSerializer<T: BaseMappable>: ResponseSerializer {
|
||||
/// The `JSONDecoder` instance used to decode responses.
|
||||
public let decoder: DataDecoder = JSONDecoder()
|
||||
/// HTTP response codes for which empty responses are allowed.
|
||||
public let emptyResponseCodes: Set<Int>
|
||||
/// HTTP request methods for which empty responses are allowed.
|
||||
public let emptyRequestMethods: Set<HTTPMethod>
|
||||
|
||||
public let keyPath: String?
|
||||
public let context: MapContext?
|
||||
public let object: T?
|
||||
|
||||
public let serializeCallback: (URLRequest?,HTTPURLResponse?, Data?,Error?) throws -> T
|
||||
|
||||
/// Creates an instance using the values provided.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - keyPath:
|
||||
/// - object:
|
||||
/// - context:
|
||||
/// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
|
||||
/// `[204, 205]`.
|
||||
/// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
|
||||
/// - serializeCallback:
|
||||
public init(_ keyPath: String?, mapToObject object: T? = nil, context: MapContext? = nil,
|
||||
emptyResponseCodes: Set<Int> = MappableResponseSerializer.defaultEmptyResponseCodes,
|
||||
emptyRequestMethods: Set<HTTPMethod> = MappableResponseSerializer.defaultEmptyRequestMethods, serializeCallback: @escaping (URLRequest?,HTTPURLResponse?, Data?,Error?) throws -> T) {
|
||||
|
||||
self.emptyResponseCodes = emptyResponseCodes
|
||||
self.emptyRequestMethods = emptyRequestMethods
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.context = context
|
||||
self.object = object
|
||||
self.serializeCallback = serializeCallback
|
||||
}
|
||||
|
||||
public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> T {
|
||||
guard error == nil else { throw error! }
|
||||
|
||||
guard let data = data, !data.isEmpty else {
|
||||
guard emptyResponseAllowed(forRequest: request, response: response) else {
|
||||
throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
|
||||
}
|
||||
|
||||
guard let emptyValue = Empty.value as? T else {
|
||||
throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
return try self.serializeCallback(request, response, data, error)
|
||||
}
|
||||
}
|
||||
|
||||
public final class MappableArrayResponseSerializer<T: BaseMappable>: ResponseSerializer {
|
||||
/// The `JSONDecoder` instance used to decode responses.
|
||||
public let decoder: DataDecoder = JSONDecoder()
|
||||
/// HTTP response codes for which empty responses are allowed.
|
||||
public let emptyResponseCodes: Set<Int>
|
||||
/// HTTP request methods for which empty responses are allowed.
|
||||
public let emptyRequestMethods: Set<HTTPMethod>
|
||||
|
||||
public let keyPath: String?
|
||||
public let context: MapContext?
|
||||
|
||||
public let serializeCallback: (URLRequest?,HTTPURLResponse?, Data?,Error?) throws -> [T]
|
||||
/// Creates an instance using the values provided.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - keyPath:
|
||||
/// - context:
|
||||
/// - emptyResponseCodes: The HTTP response codes for which empty responses are allowed. Defaults to
|
||||
/// `[204, 205]`.
|
||||
/// - emptyRequestMethods: The HTTP request methods for which empty responses are allowed. Defaults to `[.head]`.
|
||||
/// - serializeCallback:
|
||||
public init(_ keyPath: String?, context: MapContext? = nil, serializeCallback: @escaping (URLRequest?,HTTPURLResponse?, Data?,Error?) throws -> [T],
|
||||
emptyResponseCodes: Set<Int> = MappableArrayResponseSerializer.defaultEmptyResponseCodes,
|
||||
emptyRequestMethods: Set<HTTPMethod> = MappableArrayResponseSerializer.defaultEmptyRequestMethods) {
|
||||
self.emptyResponseCodes = emptyResponseCodes
|
||||
self.emptyRequestMethods = emptyRequestMethods
|
||||
|
||||
self.keyPath = keyPath
|
||||
self.context = context
|
||||
self.serializeCallback = serializeCallback
|
||||
}
|
||||
|
||||
public func serialize(request: URLRequest?, response: HTTPURLResponse?, data: Data?, error: Error?) throws -> [T] {
|
||||
guard error == nil else { throw error! }
|
||||
|
||||
guard let data = data, !data.isEmpty else {
|
||||
guard emptyResponseAllowed(forRequest: request, response: response) else {
|
||||
throw AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength)
|
||||
}
|
||||
|
||||
// TODO / FIX - Empty Response JSON Decodable Array Fix - "Cast from empty always fails..."
|
||||
guard let emptyValue = Empty.value as? [T] else {
|
||||
throw AFError.responseSerializationFailed(reason: .invalidEmptyResponse(type: "\(T.self)"))
|
||||
}
|
||||
|
||||
return emptyValue
|
||||
}
|
||||
return try self.serializeCallback(request, response, data, error)
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Tristan Himmelman
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
+193
@@ -0,0 +1,193 @@
|
||||
AlamofireObjectMapper
|
||||
============
|
||||
[](https://travis-ci.org/tristanhimmelman/AlamofireObjectMapper)
|
||||
[](https://github.com/tristanhimmelman/AlamofireObjectMapper)
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
|
||||
|
||||
An extension to [Alamofire](https://github.com/Alamofire/Alamofire) which automatically converts JSON response data into swift objects using [ObjectMapper](https://github.com/Hearst-DD/ObjectMapper/).
|
||||
|
||||
# Usage
|
||||
|
||||
Given a URL which returns weather data in the following form:
|
||||
```
|
||||
{
|
||||
"location": "Toronto, Canada",
|
||||
"three_day_forecast": [
|
||||
{
|
||||
"conditions": "Partly cloudy",
|
||||
"day" : "Monday",
|
||||
"temperature": 20
|
||||
},
|
||||
{
|
||||
"conditions": "Showers",
|
||||
"day" : "Tuesday",
|
||||
"temperature": 22
|
||||
},
|
||||
{
|
||||
"conditions": "Sunny",
|
||||
"day" : "Wednesday",
|
||||
"temperature": 28
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can use the extension as the follows:
|
||||
```swift
|
||||
import AlamofireObjectMapper
|
||||
|
||||
let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/d8bb95982be8a11a2308e779bb9a9707ebe42ede/sample_json"
|
||||
Alamofire.request(URL).responseObject { (response: DataResponse<WeatherResponse>) in
|
||||
|
||||
let weatherResponse = response.result.value
|
||||
print(weatherResponse?.location)
|
||||
|
||||
if let threeDayForecast = weatherResponse?.threeDayForecast {
|
||||
for forecast in threeDayForecast {
|
||||
print(forecast.day)
|
||||
print(forecast.temperature)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `WeatherResponse` object in the completion handler is a custom object which you define. The only requirement is that the object must conform to [ObjectMapper's](https://github.com/Hearst-DD/ObjectMapper/) `Mappable` protocol. In the above example, the `WeatherResponse` object looks like the following:
|
||||
|
||||
```swift
|
||||
import ObjectMapper
|
||||
|
||||
class WeatherResponse: Mappable {
|
||||
var location: String?
|
||||
var threeDayForecast: [Forecast]?
|
||||
|
||||
required init?(map: Map){
|
||||
|
||||
}
|
||||
|
||||
func mapping(map: Map) {
|
||||
location <- map["location"]
|
||||
threeDayForecast <- map["three_day_forecast"]
|
||||
}
|
||||
}
|
||||
|
||||
class Forecast: Mappable {
|
||||
var day: String?
|
||||
var temperature: Int?
|
||||
var conditions: String?
|
||||
|
||||
required init?(map: Map){
|
||||
|
||||
}
|
||||
|
||||
func mapping(map: Map) {
|
||||
day <- map["day"]
|
||||
temperature <- map["temperature"]
|
||||
conditions <- map["conditions"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The extension uses Generics to allow you to create your own custom response objects. Below is the `responseObject` function definition. Just replace `T` in the completionHandler with your custom response object and the extension handles the rest:
|
||||
```swift
|
||||
public func responseObject<T: BaseMappable>(queue: DispatchQueue? = nil, keyPath: String? = nil, mapToObject object: T? = nil, context: MapContext? = nil, completionHandler: @escaping (DataResponse<T>) -> Void) -> Self
|
||||
```
|
||||
The `responseObject` function has 4 optional parameters and a required completionHandler:
|
||||
- `queue`: The queue on which the completion handler is dispatched.
|
||||
- `keyPath`: The key path of the JSON where object mapping should be performed.
|
||||
- `mapToObject`: An object to perform the mapping on to.
|
||||
- `context`: A [context object](https://github.com/Hearst-DD/ObjectMapper/#mapping-context) that is passed to the mapping function.
|
||||
- `completionHandler`: A closure to be executed once the request has finished and the data has been mapped by ObjectMapper.
|
||||
|
||||
### Easy Mapping of Nested Objects
|
||||
|
||||
AlamofireObjectMapper supports dot notation within keys for easy mapping of nested objects. Given the following JSON String:
|
||||
```json
|
||||
"distance" : {
|
||||
"text" : "102 ft",
|
||||
"value" : 31
|
||||
}
|
||||
```
|
||||
You can access the nested objects as follows:
|
||||
```swift
|
||||
func mapping(map: Map) {
|
||||
distance <- map["distance.value"]
|
||||
}
|
||||
```
|
||||
[See complete documentation](https://github.com/Hearst-DD/ObjectMapper#easy-mapping-of-nested-objects)
|
||||
|
||||
### KeyPath
|
||||
|
||||
The `keyPath` variable is used to drill down into a JSON response and only map the data found at that `keyPath`. It supports nested values such as `data.weather` to drill down several levels in a JSON response.
|
||||
```swift
|
||||
let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/2ee8f34d21e8febfdefb2b3a403f18a43818d70a/sample_keypath_json"
|
||||
let expectation = expectationWithDescription("\(URL)")
|
||||
|
||||
Alamofire.request(URL).responseObject(keyPath: "data") { (response: DataResponse<WeatherResponse>) in
|
||||
expectation.fulfill()
|
||||
|
||||
let weatherResponse = response.result.value
|
||||
print(weatherResponse?.location)
|
||||
|
||||
if let threeDayForecast = weatherResponse?.threeDayForecast {
|
||||
for forecast in threeDayForecast {
|
||||
print(forecast.day)
|
||||
print(forecast.temperature)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# Array Responses
|
||||
If you have an endpoint that returns data in `Array` form you can map it with the following function:
|
||||
```swift
|
||||
public func responseArray<T: Mappable>(queue queue: dispatch_queue_t? = nil, keyPath: String? = nil, completionHandler: DataResponse<[T]> -> Void) -> Self
|
||||
```
|
||||
|
||||
For example, if your endpoint returns the following:
|
||||
```
|
||||
[
|
||||
{
|
||||
"conditions": "Partly cloudy",
|
||||
"day" : "Monday",
|
||||
"temperature": 20
|
||||
},
|
||||
{
|
||||
"conditions": "Showers",
|
||||
"day" : "Tuesday",
|
||||
"temperature": 22
|
||||
},
|
||||
{
|
||||
"conditions": "Sunny",
|
||||
"day" : "Wednesday",
|
||||
"temperature": 28
|
||||
}
|
||||
]
|
||||
```
|
||||
You can request and map it as follows:
|
||||
```swift
|
||||
let URL = "https://raw.githubusercontent.com/tristanhimmelman/AlamofireObjectMapper/f583be1121dbc5e9b0381b3017718a70c31054f7/sample_array_json"
|
||||
Alamofire.request(URL).responseArray { (response: DataResponse<[Forecast]>) in
|
||||
|
||||
let forecastArray = response.result.value
|
||||
|
||||
if let forecastArray = forecastArray {
|
||||
for forecast in forecastArray {
|
||||
print(forecast.day)
|
||||
print(forecast.temperature)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
# Installation
|
||||
AlamofireObjectMapper can be added to your project using [CocoaPods](https://cocoapods.org/) by adding the following line to your Podfile:
|
||||
```
|
||||
pod 'AlamofireObjectMapper', '~> 5.2'
|
||||
```
|
||||
|
||||
If you're using [Carthage](https://github.com/Carthage/Carthage) you can add a dependency on AlamofireObjectMapper by adding it to your Cartfile:
|
||||
```
|
||||
github "tristanhimmelman/AlamofireObjectMapper" ~> 5.2
|
||||
```
|
||||
Reference in New Issue
Block a user