diff --git a/AlamofireJsonToObjects.podspec b/AlamofireJsonToObjects.podspec index 6f0f214..b381dc6 100755 --- a/AlamofireJsonToObjects.podspec +++ b/AlamofireJsonToObjects.podspec @@ -8,7 +8,7 @@ Pod::Spec.new do |s| # s.name = "AlamofireJsonToObjects" -s.version = "2.3.2" +s.version = "2.4.0" s.summary = "An Alamofire extension which converts JSON response data into swift objects using EVReflection" s.description = "An Alamofire extension which converts JSON response data into swift objects using EVReflection. " s.homepage = "https://github.com/evermeer/AlamofireJsonToObjects" diff --git a/AlamofireJsonToObjects/AlamofireJsonToObjects.swift b/AlamofireJsonToObjects/AlamofireJsonToObjects.swift index ff2a891..072443c 100755 --- a/AlamofireJsonToObjects/AlamofireJsonToObjects.swift +++ b/AlamofireJsonToObjects/AlamofireJsonToObjects.swift @@ -12,6 +12,19 @@ import EVReflection import Alamofire +open class EVNetworkingObject: EVObject { + override open func initValidation(_ dict: NSDictionary) { + if dict["__response_statusCode"] != nil { + self.addStatusMessage(DeserializationStatus.Custom, message: "HTTP Status = \(dict["__response_statusCode"]!)") + } + } + + override open func propertyMapping() -> [(String?, String?)] { + return [("__response_statusCode", nil)] + } +} + + extension DataRequest { enum ErrorCode: Int { diff --git a/AlamofireJsonToObjectsTests/AlamofireJsonToObjectsTests.swift b/AlamofireJsonToObjectsTests/AlamofireJsonToObjectsTests.swift index 12f8368..4ee96fb 100755 --- a/AlamofireJsonToObjectsTests/AlamofireJsonToObjectsTests.swift +++ b/AlamofireJsonToObjectsTests/AlamofireJsonToObjectsTests.swift @@ -10,12 +10,12 @@ import XCTest import Alamofire import EVReflection -class WeatherResponse: EVObject { +class WeatherResponse: EVNetworkingObject { var location: String? var three_day_forecast: [Forecast] = [Forecast]() } -class Forecast: EVObject { +class Forecast: EVNetworkingObject { var day: String? var temperature: NSNumber? var conditions: String? @@ -44,7 +44,6 @@ class AlamofireJsonToObjectsTests: XCTestCase { Alamofire.request(URL) .responseObject { (response: DataResponse) in - exp.fulfill() if let result = response.result.value { print("\(result.description)") XCTAssertNotNil(result.location, "Location should not be nil") @@ -59,8 +58,7 @@ class AlamofireJsonToObjectsTests: XCTestCase { } else { XCTAssert(true, "no result from service") } - - + exp.fulfill() } waitForExpectations(timeout: 10) { error in @@ -68,6 +66,30 @@ class AlamofireJsonToObjectsTests: XCTestCase { } } + + func testErrorResponse() { + let URL: URLConvertible = "http://raw.githubusercontent.com/evermeer/AlamofireJsonToObjects/master/AlamofireJsonToObjectsTests/non_existing_file" + let exp = expectation(description: "\(URL)") + + Alamofire.request(URL) + .responseObject { (response: DataResponse) in + + if let result = response.result.value { + print("\(result.description)") + print("\(result.evReflectionStatuses)") + XCTAssertNotNil(result.evReflectionStatuses.first?.0 == DeserializationStatus.Custom, "A custom validation error should have been added") + XCTAssertNotNil(result.evReflectionStatuses.first?.1 == "HTTP Status = 404", "The custom validation error should be for a 404 HTTP status error") + } else { + XCTAssert(true, "no result from service") + } + exp.fulfill() + } + + waitForExpectations(timeout: 10) { error in + XCTAssertNil(error, "\(error)") + } + } + func testResponseObject2() { // This is an example of a functional test case. @@ -77,19 +99,19 @@ class AlamofireJsonToObjectsTests: XCTestCase { Alamofire.request(Router.list1()) .responseObject { (response: DataResponse) in - exp.fulfill() - if let result = response.result.value { - XCTAssertNotNil(result.location, "Location should not be nil") - XCTAssertNotNil(result.three_day_forecast, "ThreeDayForcast should not be nil") - XCTAssertEqual(result.three_day_forecast.count, 3, "ThreeDayForcast should have 2 items.") - for forecast in result.three_day_forecast { - XCTAssertNotNil(forecast.day, "day should not be nil") - XCTAssertNotNil(forecast.conditions, "conditions should not be nil") - XCTAssertNotNil(forecast.temperature, "temperature should not be nil") - } - } else { - XCTAssert(true, "Could not get result from service") + if let result = response.result.value { + XCTAssertNotNil(result.location, "Location should not be nil") + XCTAssertNotNil(result.three_day_forecast, "ThreeDayForcast should not be nil") + XCTAssertEqual(result.three_day_forecast.count, 3, "ThreeDayForcast should have 2 items.") + for forecast in result.three_day_forecast { + XCTAssertNotNil(forecast.day, "day should not be nil") + XCTAssertNotNil(forecast.conditions, "conditions should not be nil") + XCTAssertNotNil(forecast.temperature, "temperature should not be nil") } + } else { + XCTAssert(true, "Could not get result from service") + } + exp.fulfill() } waitForExpectations(timeout: 10) { error in @@ -106,7 +128,6 @@ class AlamofireJsonToObjectsTests: XCTestCase { Alamofire.request(URL, method: HTTPMethod.get, parameters: nil, encoding: URLEncoding.default, headers: nil) .responseObject { (response: DataResponse) in - exp.fulfill() if let result = response.result.value { XCTAssertNotNil(result.location, "Location should not be nil") XCTAssertNotNil(result.three_day_forecast, "ThreeDayForcast should not be nil") @@ -119,6 +140,7 @@ class AlamofireJsonToObjectsTests: XCTestCase { } else { XCTAssert(true, "Could not get result from service") } + exp.fulfill() } waitForExpectations(timeout: 10) { error in @@ -133,7 +155,6 @@ class AlamofireJsonToObjectsTests: XCTestCase { Alamofire.request(URL) .responseArray { (response: DataResponse<[Forecast]>) in - exp.fulfill() if let result = response.result.value { for forecast in result { @@ -144,7 +165,7 @@ class AlamofireJsonToObjectsTests: XCTestCase { } else { XCTAssert(true, "Service did not return a result") } - + exp.fulfill() } waitForExpectations(timeout: 10) { error in diff --git a/README.md b/README.md index 904deb0..da49a0c 100755 --- a/README.md +++ b/README.md @@ -54,12 +54,12 @@ import AlamofireJsonToObjects ## Sample code ``` -class WeatherResponse: EVObject { +class WeatherResponse: EVNetworkingObject { var location: String? var three_day_forecast: [Forecast] = [Forecast]() } -class Forecast: EVObject { +class Forecast: EVNetworkingObject { var day: String? var temperature: NSNumber? var conditions: String? @@ -105,6 +105,10 @@ The code above will pass the folowing json to the objects: ## Advanced object mapping AlamofireJsonToObjects is based on [EVReflection](https://github.com/evermeer/EVReflection) and you can use all [EVReflection](https://github.com/evermeer/EVReflection) features like property mapping, converters, validators and key kleanup. See [EVReflection](https://github.com/evermeer/EVReflection) for more information. +## Handling HTTP status >= 300 +When a network call returns a [HTTP error status](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes) (300 or highter) then this will be added to the evReflectionStatuses as a custom error. see the unit test testErrorResponse as a sample. In order to make this work, you do have to set EVNetworkingObject as your bass class and not EVObject. You then also have to be aware that if you override the initValidation or the propertyMapping function, that you also have to call the super for that function. + + ## License AlamofireJsonToObjects is available under the MIT 3 license. See the LICENSE file for more info.