Skip to content

Instantly share code, notes, and snippets.

@potmo
Created September 30, 2016 20:30
Show Gist options
  • Save potmo/9752245a3ee7ba05204a4f249b7445c3 to your computer and use it in GitHub Desktop.
Save potmo/9752245a3ee7ba05204a4f249b7445c3 to your computer and use it in GitHub Desktop.
generated-endpoint.swift
/* json to parse
{
"required_string": "test",
"optional_string": "test",
"required_int": 123,
"optional_int": 123,
"required_bool": true,
"optional_bool": true,
"required_timestamp": "2016-09-30T17:18:19Z000",
"optional_timestamp": "2016-09-30T17:18:19Z000",
"required_example_enum": "first",
"optional_example_enum": "first",
"required_example_class": {
"required_string": "test"
"optional_int": 123
},
"optional_example_class": {
"required_string": "test"
"optional_int": 123
},
"required_array": ["a", "b", "c"],
"optional_array": ["a", "b", "c"]
}
*/
/* swagger
{
"/some/path/with/{id}/etc": {
"get": {
"description": "Returns example entity",
"produces": [
"application/json"
],
"parameters": [
{
"name": "id",
"in": "path",
"description": "ID of the entity",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "An example entiry",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/pet"
}
}
}
}
}
}
}
*/
import SwiftlyJSON //https://github.com/lingoer/SwiftyJSON
import Alamofire //https://github.com/Alamofire/Alamofire
/// Example API
/// Example API Description
/// Version 0.0.1
public struct ExampleAPI {
private let sessionManager: SessionManager
public init(sessionManager: SessionManager) {
self.sessionManager = sessionManager
}
/// GET https://example.domain.com/some/path/with/{id}/etc
public func getExampleEntity(withId id: String, callback: (result: Result<ExampleEntity>) -> Void ) -> Void {
// Remember to url encode the id
let url = "https://www.example.domain.com/some/path/with/\(id)/etc"
let exampleEntity = ...
callback(.Success(exampleEntity))
// authentication is added to the session manager instead of here
let headers: HTTPHeaders = [
"Accept": "application/json"
]
// could be added for ?a=1&b=2
let parameters: Parameters = [
"foo": "bar"
]
// This is another option instead of the inlined in `request`
//let url = URL(string: "https://www.example.domain.com")!.appendingPathComponent("/some/path/with/\(id)/etc")
//var urlRequest = URLRequest(url: url)
//urlRequest.httpMethod = "GET"
//urlRequest.httpBody = entity.toJSONString()
//urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
//let encodedUrlRequest = try! URLEncoding.queryString.encode(urlRequest, with: parameters)
//.request(encodedUrlRequest)
self.sessionManager
.request(url, headers: headers, parameters: parameters, encoding: URLEncoding.default, method: .get)
.validate(statusCode: 200..<300)
.validate(contentType: ["application/json"])
.responseJSON { response in
switch response.result {
case .success(let json):
if let entity = ExampleEntry(json) {
callback(Result<ExampleEntry>.success(entiry))
} else {
callback(Result<ExampleEntry>.failure(BackendError.jsonSerialization(error: "some message"))
}
case .failure(let error):
callback(Result<ExampleEntry>.failure(error))
}
}
}
public struct ExampleEntity: Equatable, CustomStringConvertible {
/// A required String
public let requiredString: String
/// An optional String
public let optionalString: String?
/// A required Int
public let requiredInt: Int
/// An optional Int
public let optionalInt: Int?
/// A required Bool
public let requiredBool: Bool
/// An optional Bool
public let optionalBool: Bool?
/// A required Timestamp
public let requiredTimestamp: Timestamp
/// An optional Timestamp
public let optionalTimestamp: Timestamp?
/// A required ExampleEnum
public let requiredExampleEnum: ExampleEnum
/// An optional ExampleEnum
public let optionalExampleEnum: ExampleEnum?
/// A required ExampleClass
public let requiredExampleClass: ExampleClass
/// An optional ExampleClass
public let optionalExampleClass: ExampleClass?
// A required Array<String>
public let requiredArray: [String]
// An optional Array<String>
public let optionalArray: [String]?
init?(_ json: JSON?) {
guard json = json else { return nil }
guard requiredString = json["required_string"].string else { return nil}
optionalString = json["optional_string"].string
guard requiredInt = json["required_int"].int else { return nil}
optionalInt = json["optional_int"].int
guard requiredBool = json["required_bool"].bool else { return nil}
optionalBool = json["optional_bool"].bool
guard requiredTimestamp = Timestamp(json["required_timestamp"]) else { return nil}
optionalTimestamp = Timestampe(json["optional_timestamp"])
guard requiredExampleEnum = ExampleEnum(json["required_example_enum"]) else { return nil}
optionalExampleEnum = ExampleEnum(json["optional_example_enum"])
guard requiredExampleClass = ExampleClass(json["required_example_class"]) else { return nil}
optionalExampleClass = json["optional_example_class"]
// Not sure how to do this. If an element is invalid then what? remove the invalid element?
// fail the entire Array?
// Can is the array typed as [T], [T?], [T]? or [T?]?
// Can it be different rules for that?
// Also not sure if this closure thingy really compiles
guard requiredArray = {
return json.map{ (key, value) in
return value.string
}.filter{ $0 != nil }
}() else {
return nil
}
}
public func toJSON() -> JSON {
var json: JSON = [:]
json["required_string"] = requiredString
if let optionalString = optionalString { json["optional_string"] = optionalString }
json["required_int"] = requiredInt
if let optionalInt = optionalInt { json["optional_int"] = optionalInt }
json["required_bool"] = requiredBool
if let optionalBool = optionalBool { json["optional_bool"] = optionalBool }
json["required_timestamp"] = requiredTimestamp.toJSON()
if let optionalTimestamp = optionalTimestamp { json["optional_timestamp"] = optionalTimestamp.toJSON() }
json["required_example_enum"] = requiredExampleEnum.toJSON()
if let optionalExampleEnum = optionalExampleEnum { json["optional_example_enum"] = optionalExampleEnum.toJSON() }
json["required_example_class"] = requiredExampleClass.toJSON()
if let optionalExampleClass = optionalExampleClass { json["optional_example_class"] = optionalExampleClass.toJSON() }
json["required_array"] = requiredArray
if let optionalArray = optionalArray { json["optional_array"] = optionalArray }
// arrays with compex types or enums would have to array.map{ $0.toJSON() }
return json
}
// Equatable implementation
static public func ==(lhs: ExampleEntity, rhs: ExampleEntity) -> Bool {
return
a.requiredString == b.requiredString &&
a.optionalString == b.optionalString &&
a.requiredInt == b.requiredInt &&
a.optionalInt == b.optionalInt &&
a.requiredBool == b.requiredBool &&
a.optionalBool == b.optionalBool &&
a.requiredTimestamp == b.requiredTimestamp &&
a.optionalTimestamp == b.optionalTimestamp &&
a.requiredExampleEnum == b.requiredExampleEnum &&
a.optionalExampleEnum == b.optionalExampleEnum &&
a.requiredExampleClass == b.requiredExampleClass &&
a.optionalExampleClass == b.optionalExampleClass &&
a.requiredArray == b.requiredArray &&
a.optionalArray == b.optionalArray
}
// CustomStringConvertible implementation
public var description: String {
guard string = toJSON().rawString() else {
return "<invalid json>"
}
return string
}
/// Some description of the class
public enum ExampleEnum: String, Equatable, CustomStringConvertible {
// Must be Equatable and CustomStringConvertible. Gets that from string
case first = "first"
case secon = "second"
public init?(_ json: JSON?) {
guard json = json else { return nil }
guard self = init(rawValue: json.string) else { return nil }
}
}
public struct ExampleClass: Equatable, CustomStringConvertible {
// TODO: Must be Equatable.
// TODO: Must be CustomStringConvertible.
// TODO: Must have toJSON()
public let requiredString: String
public let optionalInt: Int?
public init?(json: JSON?) {
guard json = json else { return nil }
requiredString = json["required_string"].string
guard optionalInt = json["optional_int"].int else { return nil }
}
}
}
}
@potmo
Copy link
Author

potmo commented Sep 30, 2016

@dbrockman just a first stab in the dark

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment