forked from loafle/openapi-generator-original
[Swift] Use ISOFullDate for date format
This commit is contained in:
parent
40610373f6
commit
f639a312e8
@ -115,8 +115,8 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
|
||||
typeMapping.put("array", "Array");
|
||||
typeMapping.put("List", "Array");
|
||||
typeMapping.put("map", "Dictionary");
|
||||
typeMapping.put("date", "NSDate");
|
||||
typeMapping.put("Date", "NSDate");
|
||||
typeMapping.put("date", "ISOFullDate");
|
||||
typeMapping.put("Date", "ISOFullDate");
|
||||
typeMapping.put("DateTime", "NSDate");
|
||||
typeMapping.put("boolean", "Bool");
|
||||
typeMapping.put("string", "String");
|
||||
|
@ -84,6 +84,99 @@ extension NSUUID: JSONEncodable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an ISO-8601 full-date (RFC-3339).
|
||||
/// ex: 12-31-1999
|
||||
/// https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
|
||||
public final class ISOFullDate: CustomStringConvertible {
|
||||
|
||||
public let year: Int
|
||||
public let month: Int
|
||||
public let day: Int
|
||||
|
||||
public init(year year: Int, month: Int, day: Int) {
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.day = day
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSDate to an ISOFullDate. Only interested in the year, month, day components.
|
||||
|
||||
- parameter date: The date to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the year, month, day of the date.
|
||||
*/
|
||||
public static func from(date date: NSDate) -> ISOFullDate? {
|
||||
guard let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
return ISOFullDate(
|
||||
year: components.year,
|
||||
month: components.month,
|
||||
day: components.day
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts a ISO-8601 full-date string to an ISOFullDate.
|
||||
|
||||
- parameter string: The ISO-8601 full-date format string to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the string.
|
||||
*/
|
||||
public static func from(string string: String) -> ISOFullDate? {
|
||||
let components = string
|
||||
.characters
|
||||
.split("-")
|
||||
.map(String.init)
|
||||
.flatMap { Int($0) }
|
||||
guard components.count == 3 else { return nil }
|
||||
|
||||
return ISOFullDate(
|
||||
year: components[0],
|
||||
month: components[1],
|
||||
day: components[2]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts the receiver to an NSDate, in the default time zone.
|
||||
|
||||
- returns: An NSDate from the components of the receiver, in the default time zone.
|
||||
*/
|
||||
public func toDate() -> NSDate? {
|
||||
let components = NSDateComponents()
|
||||
components.year = year
|
||||
components.month = month
|
||||
components.day = day
|
||||
components.timeZone = NSTimeZone.defaultTimeZone()
|
||||
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
|
||||
return calendar?.dateFromComponents(components)
|
||||
}
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ISOFullDate: JSONEncodable {
|
||||
public func encodeToJSON() -> AnyObject {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
}
|
||||
|
||||
{{#usePromiseKit}}extension RequestBuilder {
|
||||
public func execute() -> Promise<Response<T>> {
|
||||
let deferred = Promise<Response<T>>.pendingPromise()
|
||||
|
@ -139,7 +139,16 @@ class Decoders {
|
||||
return NSDate(timeIntervalSince1970: Double(sourceInt / 1000) )
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
} {{#models}}{{#model}}
|
||||
}
|
||||
|
||||
// Decoder for ISOFullDate
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self, decoder: { (source: AnyObject) -> ISOFullDate in
|
||||
if let string = source as? String,
|
||||
let isoDate = ISOFullDate.from(string: string) {
|
||||
return isoDate
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}) {{#models}}{{#model}}
|
||||
|
||||
// Decoder for [{{{classname}}}]
|
||||
Decoders.addDecoder(clazz: [{{{classname}}}].self) { (source: AnyObject) -> [{{{classname}}}] in
|
||||
|
@ -63,6 +63,18 @@ public class SwiftCodegenTest {
|
||||
Assert.assertTrue(op.responses.get(0).isBinary);
|
||||
}
|
||||
|
||||
@Test(description = "returns ISOFullDate when response format is date")
|
||||
public void dateTest() {
|
||||
final Swagger model = new SwaggerParser().read("src/test/resources/2_0/datePropertyTest.json");
|
||||
final DefaultCodegen codegen = new SwiftCodegen();
|
||||
final String path = "/tests/dateResponse";
|
||||
final Operation p = model.getPaths().get(path).getPost();
|
||||
final CodegenOperation op = codegen.fromOperation(path, "post", p, model.getDefinitions());
|
||||
|
||||
Assert.assertEquals(op.returnType, "ISOFullDate");
|
||||
Assert.assertEquals(op.bodyParam.dataType, "ISOFullDate");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultPodAuthors() throws Exception {
|
||||
// Given
|
||||
|
@ -21,6 +21,7 @@ public class SwiftModelTest {
|
||||
.property("binary", new BinaryProperty())
|
||||
.property("byte", new ByteArrayProperty())
|
||||
.property("uuid", new UUIDProperty())
|
||||
.property("dateOfBirth", new DateProperty())
|
||||
.required("id")
|
||||
.required("name")
|
||||
.discriminator("test");
|
||||
@ -30,7 +31,7 @@ public class SwiftModelTest {
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 6);
|
||||
Assert.assertEquals(cm.vars.size(), 7);
|
||||
Assert.assertEquals(cm.discriminator,"test");
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
@ -91,9 +92,19 @@ public class SwiftModelTest {
|
||||
Assert.assertEquals(property6.name, "uuid");
|
||||
Assert.assertNull(property6.defaultValue);
|
||||
Assert.assertEquals(property6.baseType, "NSUUID");
|
||||
Assert.assertNull(property6.hasMore);
|
||||
Assert.assertTrue(property6.hasMore);
|
||||
Assert.assertNull(property6.required);
|
||||
Assert.assertTrue(property6.isNotContainer);
|
||||
|
||||
final CodegenProperty property7 = cm.vars.get(6);
|
||||
Assert.assertEquals(property7.baseName, "dateOfBirth");
|
||||
Assert.assertEquals(property7.datatype, "ISOFullDate");
|
||||
Assert.assertEquals(property7.name, "dateOfBirth");
|
||||
Assert.assertNull(property7.defaultValue);
|
||||
Assert.assertEquals(property7.baseType, "ISOFullDate");
|
||||
Assert.assertNull(property7.hasMore);
|
||||
Assert.assertNull(property7.required);
|
||||
Assert.assertTrue(property7.isNotContainer);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"description": "This is a sample server Petstore server. You can find out more about Swagger at <a href=\"http://swagger.io\">http://swagger.io</a> or on irc.freenode.net, #swagger. For this sample, you can use the api key \"special-key\" to test the authorization filters",
|
||||
"version": "1.0.0",
|
||||
"title": "Swagger Petstore",
|
||||
"termsOfService": "http://helloreverb.com/terms/",
|
||||
"license": {
|
||||
"name": "Apache 2.0",
|
||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
}
|
||||
},
|
||||
"basePath": "/v2",
|
||||
"schemes": [
|
||||
"http"
|
||||
],
|
||||
"paths": {
|
||||
"/tests/dateResponse": {
|
||||
"post": {
|
||||
"summary": "Echo test",
|
||||
"operationId": "echotest",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "InputDate",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OutputDate",
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -833,6 +833,10 @@
|
||||
"username": {
|
||||
"type": "string"
|
||||
},
|
||||
"dateOfBirth": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"firstName": {
|
||||
"type": "string"
|
||||
},
|
||||
|
@ -179,6 +179,7 @@ public class UserAPI: APIBase {
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
@ -198,6 +199,7 @@ public class UserAPI: APIBase {
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
|
@ -83,4 +83,97 @@ extension NSUUID: JSONEncodable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an ISO-8601 full-date (RFC-3339).
|
||||
/// ex: 12-31-1999
|
||||
/// https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
|
||||
public final class ISOFullDate: CustomStringConvertible {
|
||||
|
||||
public let year: Int
|
||||
public let month: Int
|
||||
public let day: Int
|
||||
|
||||
public init(year year: Int, month: Int, day: Int) {
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.day = day
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSDate to an ISOFullDate. Only interested in the year, month, day components.
|
||||
|
||||
- parameter date: The date to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the year, month, day of the date.
|
||||
*/
|
||||
public static func from(date date: NSDate) -> ISOFullDate? {
|
||||
guard let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
return ISOFullDate(
|
||||
year: components.year,
|
||||
month: components.month,
|
||||
day: components.day
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts a ISO-8601 full-date string to an ISOFullDate.
|
||||
|
||||
- parameter string: The ISO-8601 full-date format string to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the string.
|
||||
*/
|
||||
public static func from(string string: String) -> ISOFullDate? {
|
||||
let components = string
|
||||
.characters
|
||||
.split("-")
|
||||
.map(String.init)
|
||||
.flatMap { Int($0) }
|
||||
guard components.count == 3 else { return nil }
|
||||
|
||||
return ISOFullDate(
|
||||
year: components[0],
|
||||
month: components[1],
|
||||
day: components[2]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts the receiver to an NSDate, in the default time zone.
|
||||
|
||||
- returns: An NSDate from the components of the receiver, in the default time zone.
|
||||
*/
|
||||
public func toDate() -> NSDate? {
|
||||
let components = NSDateComponents()
|
||||
components.year = year
|
||||
components.month = month
|
||||
components.day = day
|
||||
components.timeZone = NSTimeZone.defaultTimeZone()
|
||||
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
|
||||
return calendar?.dateFromComponents(components)
|
||||
}
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ISOFullDate: JSONEncodable {
|
||||
public func encodeToJSON() -> AnyObject {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,6 +141,15 @@ class Decoders {
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}
|
||||
|
||||
// Decoder for ISOFullDate
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self, decoder: { (source: AnyObject) -> ISOFullDate in
|
||||
if let string = source as? String,
|
||||
let isoDate = ISOFullDate.from(string: string) {
|
||||
return isoDate
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
})
|
||||
|
||||
// Decoder for [Category]
|
||||
Decoders.addDecoder(clazz: [Category].self) { (source: AnyObject) -> [Category] in
|
||||
return Decoders.decode(clazz: [Category].self, source: source)
|
||||
@ -215,6 +224,7 @@ class Decoders {
|
||||
let instance = User()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"])
|
||||
instance.username = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["username"])
|
||||
instance.dateOfBirth = Decoders.decodeOptional(clazz: ISOFullDate.self, source: sourceDictionary["dateOfBirth"])
|
||||
instance.firstName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["firstName"])
|
||||
instance.lastName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["lastName"])
|
||||
instance.email = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["email"])
|
||||
|
@ -11,6 +11,7 @@ import Foundation
|
||||
public class User: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var username: String?
|
||||
public var dateOfBirth: ISOFullDate?
|
||||
public var firstName: String?
|
||||
public var lastName: String?
|
||||
public var email: String?
|
||||
@ -26,6 +27,7 @@ public class User: JSONEncodable {
|
||||
var nillableDictionary = [String:AnyObject?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["username"] = self.username
|
||||
nillableDictionary["dateOfBirth"] = self.dateOfBirth?.encodeToJSON()
|
||||
nillableDictionary["firstName"] = self.firstName
|
||||
nillableDictionary["lastName"] = self.lastName
|
||||
nillableDictionary["email"] = self.email
|
||||
|
@ -17,6 +17,7 @@
|
||||
6D4EFBB71C693BED00B96B06 /* StoreAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */; };
|
||||
6D4EFBB91C693BFC00B96B06 /* UserAPITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */; };
|
||||
751C65B82F596107A3DC8ED9 /* Pods_SwaggerClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8F60AECFF321A25553B6A5B0 /* Pods_SwaggerClient.framework */; };
|
||||
C6AAAD211D8718D00016A515 /* ISOFullDateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6AAAD201D8718D00016A515 /* ISOFullDateTests.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -47,6 +48,7 @@
|
||||
A638467ACFB30852DEA51F7A /* Pods-SwaggerClient.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
B4B2BEC2ECA535C616F2F3FE /* Pods-SwaggerClientTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClientTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClientTests/Pods-SwaggerClientTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C07EC0A94AA0F86D60668B32 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
C6AAAD201D8718D00016A515 /* ISOFullDateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ISOFullDateTests.swift; sourceTree = "<group>"; };
|
||||
F65B6638217EDDC99D103B16 /* Pods_SwaggerClientTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SwaggerClientTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
FC60BDC7328C2AA916F25840 /* Pods-SwaggerClient.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwaggerClient.release.xcconfig"; path = "Pods/Target Support Files/Pods-SwaggerClient/Pods-SwaggerClient.release.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@ -129,6 +131,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6D4EFBAB1C692C6300B96B06 /* Info.plist */,
|
||||
C6AAAD201D8718D00016A515 /* ISOFullDateTests.swift */,
|
||||
6D4EFBB41C693BE200B96B06 /* PetAPITests.swift */,
|
||||
6D4EFBB61C693BED00B96B06 /* StoreAPITests.swift */,
|
||||
6D4EFBB81C693BFC00B96B06 /* UserAPITests.swift */,
|
||||
@ -473,6 +476,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
C6AAAD211D8718D00016A515 /* ISOFullDateTests.swift in Sources */,
|
||||
6D4EFBB71C693BED00B96B06 /* StoreAPITests.swift in Sources */,
|
||||
6D4EFBB91C693BFC00B96B06 /* UserAPITests.swift in Sources */,
|
||||
6D4EFBB51C693BE200B96B06 /* PetAPITests.swift in Sources */,
|
||||
|
@ -0,0 +1,83 @@
|
||||
/// Copyright 2012-2016 (C) Butterfly Network, Inc.
|
||||
|
||||
import PetstoreClient
|
||||
import XCTest
|
||||
@testable import SwaggerClient
|
||||
|
||||
final class ISOFullDateTests: XCTestCase {
|
||||
|
||||
var fullDate = ISOFullDate(year: 1999, month: 12, day: 31)
|
||||
|
||||
func testValidDate() {
|
||||
XCTAssertEqual(fullDate.year, 1999)
|
||||
XCTAssertEqual(fullDate.month, 12)
|
||||
XCTAssertEqual(fullDate.day, 31)
|
||||
}
|
||||
|
||||
func testFromDate() {
|
||||
let date = NSDate()
|
||||
let fullDate = ISOFullDate.from(date: date)
|
||||
|
||||
guard let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
|
||||
XCTAssertEqual(fullDate?.year, components.year)
|
||||
XCTAssertEqual(fullDate?.month, components.month)
|
||||
XCTAssertEqual(fullDate?.day, components.day)
|
||||
}
|
||||
|
||||
func testFromString() {
|
||||
let string = "1999-12-31"
|
||||
let fullDate = ISOFullDate.from(string: string)
|
||||
XCTAssertEqual(fullDate?.year, 1999)
|
||||
XCTAssertEqual(fullDate?.month, 12)
|
||||
XCTAssertEqual(fullDate?.day, 31)
|
||||
}
|
||||
|
||||
func testFromInvalidString() {
|
||||
XCTAssertNil(ISOFullDate.from(string: "1999-12"))
|
||||
}
|
||||
|
||||
func testToDate() {
|
||||
let fullDate = ISOFullDate(year: 1999, month: 12, day: 31)
|
||||
|
||||
guard let date = fullDate.toDate(),
|
||||
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
XCTFail()
|
||||
return
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
|
||||
XCTAssertEqual(fullDate.year, components.year)
|
||||
XCTAssertEqual(fullDate.month, components.month)
|
||||
XCTAssertEqual(fullDate.day, components.day)
|
||||
}
|
||||
|
||||
func testDescription() {
|
||||
XCTAssertEqual(fullDate.description, "1999-12-31")
|
||||
}
|
||||
|
||||
func testEncodeToJSON() {
|
||||
XCTAssertEqual(fullDate.encodeToJSON() as? String, "1999-12-31")
|
||||
}
|
||||
|
||||
}
|
@ -14,16 +14,6 @@ class UserAPITests: XCTestCase {
|
||||
|
||||
let testTimeout = 10.0
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
// Put setup code here. This method is called before the invocation of each test method in the class.
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
// Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
func testLogin() {
|
||||
let expectation = self.expectationWithDescription("testLogin")
|
||||
|
||||
@ -59,6 +49,7 @@ class UserAPITests: XCTestCase {
|
||||
|
||||
let newUser = User()
|
||||
newUser.email = "test@test.com"
|
||||
newUser.dateOfBirth = ISOFullDate.from(string: "1999-12-31")
|
||||
newUser.firstName = "Test"
|
||||
newUser.lastName = "Tester"
|
||||
newUser.id = 1000
|
||||
@ -95,6 +86,7 @@ class UserAPITests: XCTestCase {
|
||||
XCTAssert(user.lastName == "Tester", "invalid lastName")
|
||||
XCTAssert(user.password == "test!", "invalid password")
|
||||
XCTAssert(user.phone == "867-5309", "invalid phone")
|
||||
XCTAssert(user.dateOfBirth?.description == "1999-12-31", "invalid date of birth")
|
||||
|
||||
expectation.fulfill()
|
||||
}
|
||||
|
@ -259,12 +259,14 @@ public class UserAPI: APIBase {
|
||||
"password" : "aeiou",
|
||||
"userStatus" : 123,
|
||||
"phone" : "aeiou",
|
||||
"dateOfBirth" : "2000-01-23T04:56:07.000+00:00",
|
||||
"id" : 123456789,
|
||||
"email" : "aeiou",
|
||||
"username" : "aeiou"
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
@ -278,12 +280,14 @@ public class UserAPI: APIBase {
|
||||
"password" : "aeiou",
|
||||
"userStatus" : 123,
|
||||
"phone" : "aeiou",
|
||||
"dateOfBirth" : "2000-01-23T04:56:07.000+00:00",
|
||||
"id" : 123456789,
|
||||
"email" : "aeiou",
|
||||
"username" : "aeiou"
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
|
@ -84,6 +84,99 @@ extension NSUUID: JSONEncodable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an ISO-8601 full-date (RFC-3339).
|
||||
/// ex: 12-31-1999
|
||||
/// https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
|
||||
public final class ISOFullDate: CustomStringConvertible {
|
||||
|
||||
public let year: Int
|
||||
public let month: Int
|
||||
public let day: Int
|
||||
|
||||
public init(year year: Int, month: Int, day: Int) {
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.day = day
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSDate to an ISOFullDate. Only interested in the year, month, day components.
|
||||
|
||||
- parameter date: The date to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the year, month, day of the date.
|
||||
*/
|
||||
public static func from(date date: NSDate) -> ISOFullDate? {
|
||||
guard let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
return ISOFullDate(
|
||||
year: components.year,
|
||||
month: components.month,
|
||||
day: components.day
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts a ISO-8601 full-date string to an ISOFullDate.
|
||||
|
||||
- parameter string: The ISO-8601 full-date format string to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the string.
|
||||
*/
|
||||
public static func from(string string: String) -> ISOFullDate? {
|
||||
let components = string
|
||||
.characters
|
||||
.split("-")
|
||||
.map(String.init)
|
||||
.flatMap { Int($0) }
|
||||
guard components.count == 3 else { return nil }
|
||||
|
||||
return ISOFullDate(
|
||||
year: components[0],
|
||||
month: components[1],
|
||||
day: components[2]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts the receiver to an NSDate, in the default time zone.
|
||||
|
||||
- returns: An NSDate from the components of the receiver, in the default time zone.
|
||||
*/
|
||||
public func toDate() -> NSDate? {
|
||||
let components = NSDateComponents()
|
||||
components.year = year
|
||||
components.month = month
|
||||
components.day = day
|
||||
components.timeZone = NSTimeZone.defaultTimeZone()
|
||||
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
|
||||
return calendar?.dateFromComponents(components)
|
||||
}
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ISOFullDate: JSONEncodable {
|
||||
public func encodeToJSON() -> AnyObject {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
}
|
||||
|
||||
extension RequestBuilder {
|
||||
public func execute() -> Promise<Response<T>> {
|
||||
let deferred = Promise<Response<T>>.pendingPromise()
|
||||
|
@ -141,6 +141,15 @@ class Decoders {
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}
|
||||
|
||||
// Decoder for ISOFullDate
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self, decoder: { (source: AnyObject) -> ISOFullDate in
|
||||
if let string = source as? String,
|
||||
let isoDate = ISOFullDate.from(string: string) {
|
||||
return isoDate
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
})
|
||||
|
||||
// Decoder for [Category]
|
||||
Decoders.addDecoder(clazz: [Category].self) { (source: AnyObject) -> [Category] in
|
||||
return Decoders.decode(clazz: [Category].self, source: source)
|
||||
@ -215,6 +224,7 @@ class Decoders {
|
||||
let instance = User()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"])
|
||||
instance.username = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["username"])
|
||||
instance.dateOfBirth = Decoders.decodeOptional(clazz: ISOFullDate.self, source: sourceDictionary["dateOfBirth"])
|
||||
instance.firstName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["firstName"])
|
||||
instance.lastName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["lastName"])
|
||||
instance.email = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["email"])
|
||||
|
@ -11,6 +11,7 @@ import Foundation
|
||||
public class User: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var username: String?
|
||||
public var dateOfBirth: ISOFullDate?
|
||||
public var firstName: String?
|
||||
public var lastName: String?
|
||||
public var email: String?
|
||||
@ -26,6 +27,7 @@ public class User: JSONEncodable {
|
||||
var nillableDictionary = [String:AnyObject?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["username"] = self.username
|
||||
nillableDictionary["dateOfBirth"] = self.dateOfBirth?.encodeToJSON()
|
||||
nillableDictionary["firstName"] = self.firstName
|
||||
nillableDictionary["lastName"] = self.lastName
|
||||
nillableDictionary["email"] = self.email
|
||||
|
@ -718,7 +718,7 @@ Requests can be suspended, resumed, and cancelled:
|
||||
Before implementing custom response serializers or object serialization methods, it's important to be prepared to handle any errors that may occur. Alamofire recommends handling these through the use of either your own `NSError` creation methods, or a simple `enum` that conforms to `ErrorType`. For example, this `BackendError` type, which will be used in later examples:
|
||||
|
||||
```swift
|
||||
enum BackendError: ErrorType {
|
||||
public enum BackendError: ErrorType {
|
||||
case Network(error: NSError)
|
||||
case DataSerialization(reason: String)
|
||||
case JSONSerialization(error: NSError)
|
||||
@ -1288,7 +1288,7 @@ The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise m
|
||||
* Potentially fund test servers to make it easier for us to test the edge cases
|
||||
* Potentially fund developers to work on one of our projects full-time
|
||||
|
||||
The community adoption of the ASF libraries has been amazing. We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward. With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members. If you use any of our libraries for work, see if your employers would be interested in donating. Our initial goal is to raise $1000 to get all our legal ducks in a row and kickstart this campaign. Any amount you can donate today to help us reach our goal would be greatly appreciated.
|
||||
The community adoption of the ASF libraries has been amazing. We are greatly humbled by your enthusiam around the projects, and want to continue to do everything we can to move the needle forward. With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members. If you use any of our libraries for work, see if your employers would be interested in donating. Our initial goal is to raise $1000 to get all our legal ducks in a row and kickstart this campaign. Any amount you can donate today to help us reach our goal would be greatly appreciated.
|
||||
|
||||
<a href='https://pledgie.com/campaigns/31474'><img alt='Click here to lend your support to: Alamofire Software Foundation and make a donation at pledgie.com !' src='https://pledgie.com/campaigns/31474.png?skin_name=chrome' border='0' ></a>
|
||||
|
||||
|
@ -44,27 +44,19 @@ public protocol URLStringConvertible {
|
||||
}
|
||||
|
||||
extension String: URLStringConvertible {
|
||||
public var URLString: String {
|
||||
return self
|
||||
}
|
||||
public var URLString: String { return self }
|
||||
}
|
||||
|
||||
extension NSURL: URLStringConvertible {
|
||||
public var URLString: String {
|
||||
return absoluteString
|
||||
}
|
||||
public var URLString: String { return absoluteString }
|
||||
}
|
||||
|
||||
extension NSURLComponents: URLStringConvertible {
|
||||
public var URLString: String {
|
||||
return URL!.URLString
|
||||
}
|
||||
public var URLString: String { return URL!.URLString }
|
||||
}
|
||||
|
||||
extension NSURLRequest: URLStringConvertible {
|
||||
public var URLString: String {
|
||||
return URL!.URLString
|
||||
}
|
||||
public var URLString: String { return URL!.URLString }
|
||||
}
|
||||
|
||||
// MARK: - URLRequestConvertible
|
||||
@ -78,9 +70,7 @@ public protocol URLRequestConvertible {
|
||||
}
|
||||
|
||||
extension NSURLRequest: URLRequestConvertible {
|
||||
public var URLRequest: NSMutableURLRequest {
|
||||
return self.mutableCopy() as! NSMutableURLRequest
|
||||
}
|
||||
public var URLRequest: NSMutableURLRequest { return self.mutableCopy() as! NSMutableURLRequest }
|
||||
}
|
||||
|
||||
// MARK: - Convenience
|
||||
@ -91,7 +81,16 @@ func URLRequest(
|
||||
headers: [String: String]? = nil)
|
||||
-> NSMutableURLRequest
|
||||
{
|
||||
let mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!)
|
||||
let mutableURLRequest: NSMutableURLRequest
|
||||
|
||||
if let request = URLString as? NSMutableURLRequest {
|
||||
mutableURLRequest = request
|
||||
} else if let request = URLString as? NSURLRequest {
|
||||
mutableURLRequest = request.URLRequest
|
||||
} else {
|
||||
mutableURLRequest = NSMutableURLRequest(URL: NSURL(string: URLString.URLString)!)
|
||||
}
|
||||
|
||||
mutableURLRequest.HTTPMethod = method.rawValue
|
||||
|
||||
if let headers = headers {
|
||||
|
@ -60,7 +60,8 @@ public class Manager {
|
||||
if let info = NSBundle.mainBundle().infoDictionary {
|
||||
let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
|
||||
let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
|
||||
let version = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
|
||||
let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
|
||||
let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
|
||||
|
||||
let osNameVersion: String = {
|
||||
let versionString: String
|
||||
@ -91,7 +92,7 @@ public class Manager {
|
||||
return "\(osName) \(versionString)"
|
||||
}()
|
||||
|
||||
return "\(executable)/\(bundle) (\(version); \(osNameVersion))"
|
||||
return "\(executable)/\(bundle) (\(appVersion)/\(appBuild)); \(osNameVersion))"
|
||||
}
|
||||
|
||||
return "Alamofire"
|
||||
|
@ -64,7 +64,7 @@ extension Manager {
|
||||
- parameter hostName: The hostname of the server to connect to.
|
||||
- parameter port: The port of the server to connect to.
|
||||
|
||||
:returns: The created stream request.
|
||||
- returns: The created stream request.
|
||||
*/
|
||||
public func stream(hostName hostName: String, port: Int) -> Request {
|
||||
return stream(.Stream(hostName, port))
|
||||
|
@ -140,7 +140,7 @@ extension Request {
|
||||
|
||||
- returns: The request.
|
||||
*/
|
||||
public func validate<S : SequenceType where S.Generator.Element == String>(contentType acceptableContentTypes: S) -> Self {
|
||||
public func validate<S: SequenceType where S.Generator.Element == String>(contentType acceptableContentTypes: S) -> Self {
|
||||
return validate { _, response in
|
||||
guard let validData = self.delegate.data where validData.length > 0 else { return .Success }
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
PODS:
|
||||
- Alamofire (3.4.1)
|
||||
- Alamofire (3.4.2)
|
||||
- OMGHTTPURLRQ (3.1.3):
|
||||
- OMGHTTPURLRQ/RQ (= 3.1.3)
|
||||
- OMGHTTPURLRQ/FormURLEncode (3.1.3)
|
||||
@ -31,7 +31,7 @@ EXTERNAL SOURCES:
|
||||
:path: "../"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: 01a82e2f6c0f860ade35534c8dd88be61bdef40c
|
||||
Alamofire: 6aa33201d20d069e1598891cf928883ff1888c7a
|
||||
OMGHTTPURLRQ: a547be1b9721ddfbf9d08aab56ab72dc4c1cc417
|
||||
PetstoreClient: 24135348a992f2cbd76bc324719173b52e864cdc
|
||||
PromiseKit: 4e8127c22a9b29d1b44958ab2ec762ea6115cbfb
|
||||
|
@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>3.4.1</string>
|
||||
<string>3.4.2</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
|
@ -275,6 +275,7 @@ public class UserAPI: APIBase {
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
@ -294,6 +295,7 @@ public class UserAPI: APIBase {
|
||||
}}, {contentType=application/xml, example=<User>
|
||||
<id>123456</id>
|
||||
<username>string</username>
|
||||
<dateOfBirth>2000-01-23T04:56:07.000Z</dateOfBirth>
|
||||
<firstName>string</firstName>
|
||||
<lastName>string</lastName>
|
||||
<email>string</email>
|
||||
|
@ -83,4 +83,97 @@ extension NSUUID: JSONEncodable {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an ISO-8601 full-date (RFC-3339).
|
||||
/// ex: 12-31-1999
|
||||
/// https://xml2rfc.tools.ietf.org/public/rfc/html/rfc3339.html#anchor14
|
||||
public final class ISOFullDate: CustomStringConvertible {
|
||||
|
||||
public let year: Int
|
||||
public let month: Int
|
||||
public let day: Int
|
||||
|
||||
public init(year year: Int, month: Int, day: Int) {
|
||||
self.year = year
|
||||
self.month = month
|
||||
self.day = day
|
||||
}
|
||||
|
||||
/**
|
||||
Converts an NSDate to an ISOFullDate. Only interested in the year, month, day components.
|
||||
|
||||
- parameter date: The date to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the year, month, day of the date.
|
||||
*/
|
||||
public static func from(date date: NSDate) -> ISOFullDate? {
|
||||
guard let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian) else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let components = calendar.components(
|
||||
[
|
||||
.Year,
|
||||
.Month,
|
||||
.Day,
|
||||
],
|
||||
fromDate: date
|
||||
)
|
||||
return ISOFullDate(
|
||||
year: components.year,
|
||||
month: components.month,
|
||||
day: components.day
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts a ISO-8601 full-date string to an ISOFullDate.
|
||||
|
||||
- parameter string: The ISO-8601 full-date format string to convert.
|
||||
|
||||
- returns: An ISOFullDate constructed from the string.
|
||||
*/
|
||||
public static func from(string string: String) -> ISOFullDate? {
|
||||
let components = string
|
||||
.characters
|
||||
.split("-")
|
||||
.map(String.init)
|
||||
.flatMap { Int($0) }
|
||||
guard components.count == 3 else { return nil }
|
||||
|
||||
return ISOFullDate(
|
||||
year: components[0],
|
||||
month: components[1],
|
||||
day: components[2]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
Converts the receiver to an NSDate, in the default time zone.
|
||||
|
||||
- returns: An NSDate from the components of the receiver, in the default time zone.
|
||||
*/
|
||||
public func toDate() -> NSDate? {
|
||||
let components = NSDateComponents()
|
||||
components.year = year
|
||||
components.month = month
|
||||
components.day = day
|
||||
components.timeZone = NSTimeZone.defaultTimeZone()
|
||||
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
|
||||
return calendar?.dateFromComponents(components)
|
||||
}
|
||||
|
||||
// MARK: CustomStringConvertible
|
||||
|
||||
public var description: String {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ISOFullDate: JSONEncodable {
|
||||
public func encodeToJSON() -> AnyObject {
|
||||
return "\(year)-\(month)-\(day)"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -141,6 +141,15 @@ class Decoders {
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
}
|
||||
|
||||
// Decoder for ISOFullDate
|
||||
Decoders.addDecoder(clazz: ISOFullDate.self, decoder: { (source: AnyObject) -> ISOFullDate in
|
||||
if let string = source as? String,
|
||||
let isoDate = ISOFullDate.from(string: string) {
|
||||
return isoDate
|
||||
}
|
||||
fatalError("formatter failed to parse \(source)")
|
||||
})
|
||||
|
||||
// Decoder for [Category]
|
||||
Decoders.addDecoder(clazz: [Category].self) { (source: AnyObject) -> [Category] in
|
||||
return Decoders.decode(clazz: [Category].self, source: source)
|
||||
@ -215,6 +224,7 @@ class Decoders {
|
||||
let instance = User()
|
||||
instance.id = Decoders.decodeOptional(clazz: Int64.self, source: sourceDictionary["id"])
|
||||
instance.username = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["username"])
|
||||
instance.dateOfBirth = Decoders.decodeOptional(clazz: ISOFullDate.self, source: sourceDictionary["dateOfBirth"])
|
||||
instance.firstName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["firstName"])
|
||||
instance.lastName = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["lastName"])
|
||||
instance.email = Decoders.decodeOptional(clazz: String.self, source: sourceDictionary["email"])
|
||||
|
@ -11,6 +11,7 @@ import Foundation
|
||||
public class User: JSONEncodable {
|
||||
public var id: Int64?
|
||||
public var username: String?
|
||||
public var dateOfBirth: ISOFullDate?
|
||||
public var firstName: String?
|
||||
public var lastName: String?
|
||||
public var email: String?
|
||||
@ -26,6 +27,7 @@ public class User: JSONEncodable {
|
||||
var nillableDictionary = [String:AnyObject?]()
|
||||
nillableDictionary["id"] = self.id?.encodeToJSON()
|
||||
nillableDictionary["username"] = self.username
|
||||
nillableDictionary["dateOfBirth"] = self.dateOfBirth?.encodeToJSON()
|
||||
nillableDictionary["firstName"] = self.firstName
|
||||
nillableDictionary["lastName"] = self.lastName
|
||||
nillableDictionary["email"] = self.email
|
||||
|
Loading…
x
Reference in New Issue
Block a user