- Hands-On Server-Side Web Development with Swift
- Angus Yeung
- 455字
- 2021-06-10 19:00:24
Modeling your data with content type
As a starter, use the following commands in the Terminal to create a new application myJournal from Vapor's boilerplate project:
$ vapor new myJournal
$ cd myJournal
$ vapor xcode
Create a new directory, /Sources/App/Models, in Xcode, and add a new Swift file, Entry.swift, to the newly created directory:
// Entry.swift
import Vapor
struct Entry {
var id: String // [1]
var title: String?
var content: String?
init(id: String, title: String? = nil, content: String? = nil) {
self.id = id
self.title = title
self.content = content
}
}
Entry is a simple structure representing a journal entry. It has three fields and an initializer. The id string field is a Universal Unique Identifier (UUID) that will uniquely identify an Entry item.
Vapor 3 offers the Content type for you to parse and serialize specific data types conveniently. Content is built upon Codable to take advantage of the new data-handling infrastructure introduced in Swift 4.0. Codable makes encoding and parsing JSON extremely easy.
To add the implicit JSON format conversion to your data structure, you simply make sure your data structure conforms to the Content type:
struct Entry: Content {
...
}
In addition to JSON, the Content type can be used to represent various other format types, such as protobuf, URLEncodedForm, and multipart. You can parse and serialize content of all supported types using the same API in Vapor.
Vapor would parse the following HTTP request sent to your application:
POST /new HTTP/1.1
Content-Type: application/json
{
"id": "999",
"title": "My First Day at College",
"content": "Met with a lot of people."
}
The key names and data types of input data exactly matches with that of the struct you've created.
Every HTTP request has a content container. When you conform Entry to Content type, Vapor will be able to decode the HTTP request message and create a new Entry object that represents the decoded content.
The following code shows how to process a request via an HTTP POST:
router.post("new") { req -> Future<HTTPStatus> in
return req.content.decode(Entry.self).map { entry in
print("Appended a new entry: \(entry)")
return HTTPStatus.ok
}
}
The decode() function returns a future for HTTPStatus. Future is the value you'll receive at a later time when an asynchronous process is complete. Decoding content from a request is considered to be asynchronous because it takes time to process the multiple parts decomposed from the content.
The following shows how a HTTP GET request is handled:
router.get("get") { req -> Entry in
return Entry(id: "999", title: "First Day", content: "Lots of fun")
}
It will return JSON-encoded data of Entry and adds a default HTTP response with a 200 OK status code.