├── Tests ├── LinuxMain.swift └── Perfect-JSON-APITests │ └── Perfect_JSON_APITests.swift ├── Package.swift ├── Sources ├── person.swift ├── people.swift └── main.swift ├── .gitignore ├── Example-PeopleAPI.postman_collection ├── README.zh_CN.md └── README.md /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Perfect_JSON_APITests 3 | 4 | XCTMain([ 5 | testCase(Perfect_JSON_APITests.allTests), 6 | ]) 7 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // Generated automatically by Perfect Assistant Application 2 | // Date: 2017-10-10 14:04:34 +0000 3 | import PackageDescription 4 | let package = Package( 5 | name: "Perfect-JSON-API", 6 | targets: [], 7 | dependencies: [ 8 | .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 3), 9 | ] 10 | ) 11 | -------------------------------------------------------------------------------- /Tests/Perfect-JSON-APITests/Perfect_JSON_APITests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Perfect_JSON_API 3 | 4 | class Perfect_JSON_APITests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct results. 8 | XCTAssertEqual(Perfect_JSON_API().text, "Hello, World!") 9 | } 10 | 11 | 12 | static var allTests : [(String, (Perfect_JSON_APITests) -> () throws -> Void)] { 13 | return [ 14 | ("testExample", testExample), 15 | ] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Sources/person.swift: -------------------------------------------------------------------------------- 1 | // 2 | // person.swift 3 | // Perfect-JSON-API 4 | // 5 | // Created by Jonathan Guthrie on 2016-09-26. 6 | // 7 | // 8 | import PerfectLib 9 | 10 | class Person : JSONConvertibleObject { 11 | 12 | static let registerName = "person" 13 | 14 | var firstName: String = "" 15 | var lastName: String = "" 16 | var email: String = "" 17 | 18 | var fullName: String { 19 | return "\(firstName) \(lastName)" 20 | } 21 | 22 | init(firstName: String, lastName: String, email: String) { 23 | self.firstName = firstName 24 | self.lastName = lastName 25 | self.email = email 26 | } 27 | 28 | override public func setJSONValues(_ values: [String : Any]) { 29 | self.firstName = getJSONValue(named: "firstName", from: values, defaultValue: "") 30 | self.lastName = getJSONValue(named: "lastName", from: values, defaultValue: "") 31 | self.email = getJSONValue(named: "email", from: values, defaultValue: "") 32 | } 33 | override public func getJSONValues() -> [String : Any] { 34 | return [ 35 | "firstName":firstName, 36 | "lastName":lastName, 37 | "email":email 38 | ] 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata 19 | 20 | ## Other 21 | *.xccheckout 22 | *.moved-aside 23 | *.xcuserstate 24 | *.xcscmblueprint 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | 30 | ## Playgrounds 31 | timeline.xctimeline 32 | playground.xcworkspace 33 | 34 | # Swift Package Manager 35 | # 36 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 37 | # Packages/ 38 | .build/ 39 | 40 | # CocoaPods 41 | # 42 | # We recommend against adding the Pods directory to your .gitignore. However 43 | # you should judge for yourself, the pros and cons are mentioned at: 44 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 45 | # 46 | # Pods/ 47 | 48 | # Carthage 49 | # 50 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 51 | # Carthage/Checkouts 52 | 53 | Carthage/Build 54 | 55 | # fastlane 56 | # 57 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 58 | # screenshots whenever they are needed. 59 | # For more information about the recommended setup visit: 60 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 61 | 62 | fastlane/report.xml 63 | fastlane/screenshots 64 | 65 | Packages/ 66 | *.xcodeproj 67 | buildlinux 68 | Package.resolved 69 | PADockerfile_build 70 | .build_lin 71 | -------------------------------------------------------------------------------- /Sources/people.swift: -------------------------------------------------------------------------------- 1 | // 2 | // people.swift 3 | // Perfect-JSON-API 4 | // 5 | // Created by Jonathan Guthrie on 2016-09-26. 6 | // 7 | // 8 | 9 | import PerfectHTTP 10 | 11 | public class People { 12 | // Container for array of type Person 13 | var data = [Person]() 14 | 15 | // Populating with a mock data object 16 | init(){ 17 | data = [ 18 | Person(firstName: "Sarah", lastName: "Conner", email: "sarah.conner@mailinator.com"), 19 | Person(firstName: "John", lastName: "Conner", email: "jane.smith@mailinator.com"), 20 | Person(firstName: "Kyle", lastName: "Reese", email: "kyle.reese@mailinator.com"), 21 | Person(firstName: "Marcus", lastName: "Wright", email: "marcus.wright@mailinator.com") 22 | ] 23 | } 24 | 25 | // A simple JSON encoding function for listing data members. 26 | // Ordinarily in an API list directive, cursor commands would be included. 27 | public func list() -> String { 28 | return toString() 29 | } 30 | 31 | // Accepts the HTTPRequest object and adds a new Person from post params. 32 | public func add(_ request: HTTPRequest) -> String { 33 | let new = Person( 34 | firstName: request.param(name: "firstName") ?? "", 35 | lastName: request.param(name: "lastName") ?? "", 36 | email: request.param(name: "email") ?? "" 37 | ) 38 | data.append(new) 39 | return toString() 40 | } 41 | 42 | // Accepts raw JSON string, to be converted to JSON and consumed. 43 | public func add(_ json: String) -> String { 44 | do { 45 | let incoming = try json.jsonDecode() as! [String: String] 46 | let new = Person( 47 | firstName: incoming["firstName"] ?? "", 48 | lastName: incoming["lastName"] ?? "", 49 | email: incoming["email"] ?? "" 50 | ) 51 | data.append(new) 52 | } catch { 53 | return "ERROR" 54 | } 55 | return toString() 56 | } 57 | 58 | 59 | // Convenient encoding method that returns a string from JSON objects. 60 | private func toString() -> String { 61 | var out = [String]() 62 | 63 | for m in self.data { 64 | do { 65 | out.append(try m.jsonEncodedString()) 66 | } catch { 67 | print(error) 68 | } 69 | } 70 | return "[\(out.joined(separator: ","))]" 71 | } 72 | 73 | } 74 | 75 | -------------------------------------------------------------------------------- /Example-PeopleAPI.postman_collection: -------------------------------------------------------------------------------- 1 | { 2 | "variables": [], 3 | "info": { 4 | "name": "Example - People API", 5 | "_postman_id": "d63cdf2d-64b6-6ea1-3d96-bc651cbf0c3f", 6 | "description": "", 7 | "schema": "https://schema.getpostman.com/json/collection/v2.0.0/collection.json" 8 | }, 9 | "item": [ 10 | { 11 | "name": "http://localhost:8181/ - Hello World", 12 | "request": { 13 | "url": "http://localhost:8181/", 14 | "method": "GET", 15 | "header": [], 16 | "body": { 17 | "mode": "formdata", 18 | "formdata": [] 19 | }, 20 | "description": "" 21 | }, 22 | "response": [] 23 | }, 24 | { 25 | "name": "http://localhost:8181/api/v1/people", 26 | "request": { 27 | "url": "http://localhost:8181/api/v1/people", 28 | "method": "GET", 29 | "header": [], 30 | "body": { 31 | "mode": "formdata", 32 | "formdata": [] 33 | }, 34 | "description": "" 35 | }, 36 | "response": [] 37 | }, 38 | { 39 | "name": "http://localhost:8181/api/v1/people", 40 | "request": { 41 | "url": "http://localhost:8181/api/v1/people", 42 | "method": "POST", 43 | "header": [], 44 | "body": { 45 | "mode": "formdata", 46 | "formdata": [ 47 | { 48 | "key": "firstName", 49 | "value": "Arnold", 50 | "type": "text", 51 | "enabled": true 52 | }, 53 | { 54 | "key": "lastName", 55 | "value": "T1000", 56 | "type": "text", 57 | "enabled": true 58 | }, 59 | { 60 | "key": "email", 61 | "value": "t1000@mailinator.com", 62 | "type": "text", 63 | "enabled": true 64 | } 65 | ] 66 | }, 67 | "description": "" 68 | }, 69 | "response": [] 70 | }, 71 | { 72 | "name": "http://localhost:8181/api/v1/people/json", 73 | "request": { 74 | "url": "http://localhost:8181/api/v1/people/json", 75 | "method": "POST", 76 | "header": [ 77 | { 78 | "key": "Content-Type", 79 | "value": "application/json", 80 | "description": "" 81 | } 82 | ], 83 | "body": { 84 | "mode": "raw", 85 | "raw": "{\n \"email\": \"test@example.com\",\n \"firstName\": \"Test\",\n \"lastName\": \"User\"\n}" 86 | }, 87 | "description": "" 88 | }, 89 | "response": [] 90 | } 91 | ] 92 | } -------------------------------------------------------------------------------- /Sources/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // Perfect JSON API Example 4 | // 5 | // Created by Jonathan Guthrie on 2016-09-26. 6 | // Copyright (C) 2015 PerfectlySoft, Inc. 7 | // 8 | //===----------------------------------------------------------------------===// 9 | // 10 | // This source file is part of the Perfect.org open source project 11 | // 12 | // Copyright (c) 2015 - 2016 PerfectlySoft Inc. and the Perfect project authors 13 | // Licensed under Apache License v2.0 14 | // 15 | // See http://perfect.org/licensing.html for license information 16 | // 17 | //===----------------------------------------------------------------------===// 18 | // 19 | 20 | import PerfectLib 21 | import PerfectHTTP 22 | import PerfectHTTPServer 23 | 24 | // Create HTTP server. 25 | let server = HTTPServer() 26 | 27 | // Create the container variable for routes to be added to. 28 | var routes = Routes() 29 | 30 | // Register your own routes and handlers 31 | // This is an example "Hello, world!" HTML route 32 | routes.add(method: .get, uri: "/", handler: { 33 | request, response in 34 | // Setting the response content type explicitly to text/html 35 | response.setHeader(.contentType, value: "text/html") 36 | // Adding some HTML to the response body object 37 | response.appendBody(string: "
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
4 |
5 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |