我有一个用Vapor编写的API.我想按照
JSON API规范.
我正在努力理解如何以正确的格式创建我的响应对象.
例如,我希望我的回复结构如此……
{ "links": { "self": "http://example.com/dish","next": "http://example.com/dish?page=2","last": "http://example.com/dish?page=10" },"data": [{ "title": "Spag Bol","course": "main","description": "BasGetti","price": 3.9900000000000002 },{ "title": "Ice Cream","course": "desert","description": "Vanilla","price": 0.98999999999999999 }] }
如果POST到此端点,我可以非常简单地返回数据的内容(伪代码)
router.post(dish.self,at: "api/dish") { req,data -> Future<dish> in return Future.map(on: req,{ () -> dish in data.id = 001 return data }) }
我尝试创建一个ApiResponse类并传入数据,以便我可以构造响应,但这不适用于错误无法将类型’ApiResonse’的返回表达式转换为返回类型’dish’
router.post(dish.self,data -> Future<dish> in return Future.map(on: req,{ () -> dish in data.id = 001 return ApiResonse(links: Links(self: "http://google.com",next: "http://google.com",last: "http://google.com"),data: data) }) }
我不知道怎么能这样做.这些是尝试过的课程
final class dish: Content { var id: Int? var title: String var description: String var course: String var price: Double init(title: String,description: String,course: String,price: Double) { self.title = title self.description = description self.course = course self.price = price } } struct Links { var `self`: String? var next: String? var last: String? } class ApiResonse { var links: Links? var data: Any init(links: Links,data: Any) { self.links = links self.data = data } }
我是否需要使用泛型来设置响应类?有人能提供一个例子吗?
解决方法
>复合对象ApiResponse中的每个类或结构都需要符合内容协议. Content协议包括用于JSON解码和编码的Codable协议.
>请注意,Any不符合Codable协议,因此Any不能用作Response的任何组成部分.有关更多详细信息,请参见 Vapor Docs: “Using Content”.
>请注意,Any不符合Codable协议,因此Any不能用作Response的任何组成部分.有关更多详细信息,请参见 Vapor Docs: “Using Content”.
In Vapor 3,all content types (JSON,protobuf,URLEncodedForm,Multipart,etc) are treated the same. All you need to parse and serialize content is a Codable class or struct.
>完全符合Content的对象或复合对象可用作Responseencodable响应.
>当每个路由端点解析为特定的符合内容协议的类型时,ApiResponse模型可以是通用的.
以下代码的示例项目位于GitHub: VaporExamplesLab/Example-SO-VaporJsonResponse.
示例模型
struct dish: Content { var id: Int? var title: String var description: String var course: String var price: Double init(id: Int? = nil,title: String,price: Double) { self.id = id self.title = title self.description = description self.course = course self.price = price } } struct Links: Content { var current: String? var next: String? var last: String? } struct ApiResponse: Content { var links: Links? var dishes: [dish] init(links: Links,dishes: [dish]) { self.links = links self.dishes = dishes } }
示例POST:返回ApiResponse
router.post(dish.self,at: "api/dish") { (request: Request,dish: dish) -> ApiResponse in var dishMutable = dish dishMutable.id = 001 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return ApiResponse(links: links,dishes: [dishMutable]) }
示例POST:返回Future< ApiResponse>
router.post(dish.self,at: "api/dish-future") { (request: Request,dish: dish) -> Future<ApiResponse> in var dishMutable = dish dishMutable.id = 002 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return Future.map(on: request,{ () -> ApiResponse in return ApiResponse(links: links,dishes: [dishMutable]) }) }
收到JSON响应
{ "links": { "current": "http://example.com","next": "http://example.com","last": "http://example.com" },"dishes": [ { "id": 1,"title": "Aztec Salad","description": "Flavorful Southwestern ethos with sweet potatos and black beans.","course": "salad","price": 1.82 } ] }
通用模型
struct ApiResponseGeneric<T> : Content where T: Content { var links: Links? var data: T init(links: Links,data: T) { self.links = links self.data = data } }
具体路线终点
router.post(dish.self,at: "api/dish-generic-future") { (request: Request,dish: dish) -> Future<ApiResponseGeneric<[dish]>> in var dishMutable = dish dishMutable.id = 004 var links = Links() links.current = "http://example.com" links.next = "http://example.com" links.last = "http://example.com" return Future.map(on: request,{ () -> ApiResponseGeneric<[dish]> in return ApiResponseGeneric<[dish]>(links: links,data: [dishMutable]) }) }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。